private void кнопка_Click(object sender, EventArgs e)
{
// Проверяю существует ли такой TabPage. Иначе сл. код
TabPage myTabPage = new TabPage("Список");
myTabPage.Name = "Список";
tabControl2.TabPages.Add(myTabPage);
tabControl2.SelectedTab = myTabPage;
DataGridView DGV = SetupDataGridView(myTabPage, "Us");
// Заполняю DGV
dataGridView1.ClearSelection();
}
[c#] DataGridView, созданный программно, как к нему обратиться?
У меня есть форма. В ней есть TabContro. (Это все из конструктора)
Далее я программно создаю TabPage и DataGridView (Помещенный в него).
Вот так я создаю TabPage:
Код:
Вот так создаю DGV:
Код:
private DataGridView SetupDataGridView(TabPage ob, string name)
{
DataGridView DGV = new DataGridView();
ob.Controls.Add(DGV);
// Тут настраиваю внешний вид... затем
DGV.CellDoubleClick += new System.Windows.Forms.DataGridViewCellEventHandler(DGV_CellDoubleClick); // Добавляю событие
return DGV;
}
{
DataGridView DGV = new DataGridView();
ob.Controls.Add(DGV);
// Тут настраиваю внешний вид... затем
DGV.CellDoubleClick += new System.Windows.Forms.DataGridViewCellEventHandler(DGV_CellDoubleClick); // Добавляю событие
return DGV;
}
Как в "DGV_CellDoubleClick" мне получить текущий DataGridView?
Код:
private void DGV_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
DataGridView dgv = sender as DataGridView;
// дальше работаем с dgv
}
{
DataGridView dgv = sender as DataGridView;
// дальше работаем с dgv
}
Отмечу ещё: если контролы динамически не только создаются, но и удаляются, то нужно обязательно отписываться от событий, на которые подписались. Иначе возможны утечки памяти. Т. е. перед удалением контрола нужно:
Код:
DGV.CellDoubleClick -= DGV_CellDoubleClick;
Чето я об этом даже и не подумал))
Отдельное спасибо за замечание по поводу удаления подписки.
То-есть есть TabPage (созданный в студии), в нем программно создаем SplitContainer, в первой панели DGV, а во второй ListView. При нажатии на DGV необходимо заполнить ListView.
У каждого элемента есть имя (тоесть .Name).
Можно ли как-то получить коллекцию компонентов TabPage-а? Или возможно есть другие способы на прямую обратиться к ListView-у?
Но, по моему, в данном случае можно просто использовать ссылку на созданный программно ListView.
Цитата: koodeer
У любого компонента есть свойство Controls, которое содержит коллекцию расположенных на нём компонентов. Можно через него добраться до нужного.
Но, по моему, в данном случае можно просто использовать ссылку на созданный программно ListView.
Но, по моему, в данном случае можно просто использовать ссылку на созданный программно ListView.
Сейчас я так и делаю:
Код:
ListView LV;
bool flStop = false;
for (int i = 0; i < tabControl2.Controls.Count; i++)
{
if ("TP" == tabControl2.Controls.Name)
{
TabPage TP = tabControl2.Controls as TabPage;
for (int j = 0; j < TP.Controls.Count; j++)
{
if ("SC" == TP.Controls[j].Name)
{
SplitContainer SC = TP.Controls[j] as SplitContainer;
for (int k = 0; k < SC.Panel2.Controls.Count; k++)
{
if ("TC" == SC.Panel2.Controls[k].Name)
{
TabControl TC = SC.Panel2.Controls[k] as TabControl;
for (int l = 0; l < TC.Controls.Count; l++)
{
if ("Файлы" == TC.Controls[l].Name)
{
TabPage TP2 = TC.Controls[l] as TabPage;
for (int m = 0; m < TP2.Controls.Count; m++)
{
if ("LV" == TP2.Controls[m].Name)
{
LV = TP2.Controls[m] as ListView;
st = new ListFiles().ListFile(LV, FileDir);
flStop = true;
break;
}
}
}
if (flStop) { break; }
}
}
if (flStop) { break; }
}
}
if (flStop) { break; }
}
}
if (flStop) { break; }
}
bool flStop = false;
for (int i = 0; i < tabControl2.Controls.Count; i++)
{
if ("TP" == tabControl2.Controls.Name)
{
TabPage TP = tabControl2.Controls as TabPage;
for (int j = 0; j < TP.Controls.Count; j++)
{
if ("SC" == TP.Controls[j].Name)
{
SplitContainer SC = TP.Controls[j] as SplitContainer;
for (int k = 0; k < SC.Panel2.Controls.Count; k++)
{
if ("TC" == SC.Panel2.Controls[k].Name)
{
TabControl TC = SC.Panel2.Controls[k] as TabControl;
for (int l = 0; l < TC.Controls.Count; l++)
{
if ("Файлы" == TC.Controls[l].Name)
{
TabPage TP2 = TC.Controls[l] as TabPage;
for (int m = 0; m < TP2.Controls.Count; m++)
{
if ("LV" == TP2.Controls[m].Name)
{
LV = TP2.Controls[m] as ListView;
st = new ListFiles().ListFile(LV, FileDir);
flStop = true;
break;
}
}
}
if (flStop) { break; }
}
}
if (flStop) { break; }
}
}
if (flStop) { break; }
}
}
if (flStop) { break; }
}
А по поводу ссылки, можно поподробнее?
ListView listView = new ListView();
Вот это listView и есть ссылка. Её и передавай в другие методы.
Но как эту ссылку передавать от одной функции к другой?
То-есть у меня есть функция на событие в меню:
Код:
private void OpenToolStripMenuItem_Click(object sender, EventArgs e) // Отобразить клиентов
{
// Создаю закладку
TabPage myTabPage = new TabPage(title);
myTabPage.Name = "TP";
tabControl2.TabPages.Add(myTabPage);
tabControl2.SelectedTab = myTabPage;
// Создаю сплит (SetupSplitContainer - там описываю параметры внешнего вида и т.д.)
SplitContainer SC = SetupSplitContainer("SC");
myTabPage.Controls.Add(SC);
// Создай DGV SetupDataGridView - там описываю параметры внешнего вида и т.д.)
DataGridView DGV = SetupDataGridView("Clients");
SC.Panel1.Controls.Add(DGV);
// Создаю еще кучу всяких форм, затем сам ListView:
ListView LV = SetupListView("LV");
TP.Controls.Add(LV);
LV.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.SetupColumnHeader("Имя", 90, false),
this.SetupColumnHeader("Размер", 90, true),
this.SetupColumnHeader("Тип", 90, true),
this.SetupColumnHeader("Изменен", 90, false)
});
// Дальше заполняю грид (пока только его)
}
}
{
// Создаю закладку
TabPage myTabPage = new TabPage(title);
myTabPage.Name = "TP";
tabControl2.TabPages.Add(myTabPage);
tabControl2.SelectedTab = myTabPage;
// Создаю сплит (SetupSplitContainer - там описываю параметры внешнего вида и т.д.)
SplitContainer SC = SetupSplitContainer("SC");
myTabPage.Controls.Add(SC);
// Создай DGV SetupDataGridView - там описываю параметры внешнего вида и т.д.)
DataGridView DGV = SetupDataGridView("Clients");
SC.Panel1.Controls.Add(DGV);
// Создаю еще кучу всяких форм, затем сам ListView:
ListView LV = SetupListView("LV");
TP.Controls.Add(LV);
LV.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.SetupColumnHeader("Имя", 90, false),
this.SetupColumnHeader("Размер", 90, true),
this.SetupColumnHeader("Тип", 90, true),
this.SetupColumnHeader("Изменен", 90, false)
});
// Дальше заполняю грид (пока только его)
}
}
Внутри этой функции у меня есть доступ к любому из созданных объектов, однако покинув ее, насколько я понимаю, доступ пропадает.
Дальше у меня есть функция [COLOR="sandybrown"](назовем ее DGV_RowSelect(object sender, DataGridViewCellEventArgs e) и получаю я там соответственно ссылку на грид и на позицию выделенной строки)[/COLOR], например при выделении строки в гриде, должен заполняться ListView.
Есть конечно вариант с перебором, описанный ранее.
Есть вариант с созданием public ListView, и хранением в нем ссылки на нужный в данный момент ListView. (Этот вариант я где-то в интернете читал, и мне он кажется менее удобным (правильным), чем пред идущий)
Собственно как мне из DGV_RowSelect получить ссылку на ListView (напоминаю, лежат они внутри одного, созданного программно SplitContainer-а)?
Цитата: imAlex
Есть вариант с созданием public ListView, и хранением в нем ссылки на нужный в данный момент ListView.
Этот вариант как раз правильный и самый удобный в данном случае. Делай поле класса и его используй. Только не public, а private.
допустим, набор контролов внутри TabPage-а у меня все время одинаковый. Тогда средствами "User Control" я могу создать шаблон и при создании нового TabPage-а пихать в него мой контрол. На сколько я понимаю, мой контрол будет обладать прописанными элементами, к которым я смогу обращаться на прямую (не перебирая как раньше описано и не храня ссылку). Перебирать (или хранить ссылку) мне придется только на TabPage.
Подскажите, правильно ли я мыслю? Работает ли такая схема?