2015-11-09 7 views
0

Вы даны: Ссылка на элемент управления пользовательского интерфейса (например, TextBox), расположенный внутри ASP.NET DataGrid.Получить заголовок DataGrid для данного элемента управления

Ваша задача: найти заголовок столбца DataGrid.


я нашел следующее решение, но я не особенно нравится, потому что (а) он сложен и (б) (аб) использует знания о HTML представления DataGrid:

  1. Начиная с управления пользовательского интерфейса (ctl), не пересекают вверх Parent свойство до достижения TableCell (tc) и его родительский DataGridItem (dgi).

  2. Получить индекс (index) в TableCell в Cells имущества DataGrid в (dgi.Cells.Cast<TableCell>().ToList().IndexOf(tc)).

  3. траверс дальше вверх по Parent имущества до достижения DataGrid (grid), то доступ к тексту заголовка, используя этот индекс: grid.Columns(index).HeaderText.

Я уверен, что есть более элегантное решение этой проблемы. Что это?

+0

'DataGrid' или' GridView'? В общем, нет никакой связи между вашим текстовым полем и заголовком, поэтому нет более элегантного способа. –

+0

@TimSchmelter: DataGrid. Я знаю, что GridView - это более современная альтернатива, но это унаследованный проект. – Heinzi

+0

Это уже самое лучшее, нет элегантного способа. Если это устаревший проект, можно использовать LINQ вообще? –

ответ

1

DataGrid или GridView? В общем, нет никакой связи между вашим TextBox и заголовком, поэтому нет действительно элегантного способа.

Это лучшее, что я придумал, но я сомневаюсь, что это более элегантно, чем ваш подход:

GridView:

protected void TextBox_TextChanged(object sender, EventArgs e) 
{ 
    TextBox txt = (TextBox)sender; 
    GridViewRow row = (GridViewRow)txt.NamingContainer; 
    GridView grid = (GridView)row.NamingContainer; 
    DataControlField column = grid.Columns.Cast<DataControlField>() 
     .Select((c, Index) => new { Column = c, Index }) 
     .Where(x => row.Cells[x.Index].GetControlsRecursively().Contains(txt)) 
     .Select(x => x.Column) 
     .FirstOrDefault(); 
    if (column != null) 
    { 
     string headerText = column.HeaderText; 
    } 
} 

DataGrid:

protected void TextBox_TextChanged(object sender, EventArgs e) 
{ 
    TextBox txt = (TextBox)sender; 
    DataGridItem item = (DataGridItem)txt.NamingContainer; 
    DataGrid grid = (DataGrid)item.NamingContainer; 
    DataControlField column = grid.Columns.Cast<DataControlField>() 
     .Select((c, Index) => new { Column = c, Index }) 
     .Where(x => item.Cells[x.Index].GetControlsRecursively().Contains(txt)) 
     .Select(x => x.Column) 
     .FirstOrDefault(); 
    if (column != null) 
    { 
     string headerText = column.HeaderText; 
    } 
} 

Я нахожусь используя этот метод расширения, чтобы найти элементы управления рекурсивно:

public static IEnumerable<Control> GetControlsRecursively(this Control parent) 
{ 
    foreach (Control c in parent.Controls) 
    { 
     yield return c; 

     if (c.HasControls()) 
     { 
      foreach (Control control in c.GetControlsRecursively()) 
      { 
       yield return control; 
      } 
     } 
    } 
} 

Этот подход использует коллекцию gridView.Columns в качестве источника, так как вы хотите найти столбец. Он должен найти TextBox через GridViewRow/DataGridItem и рекурсивный поиск в каждой ячейке этого товара/строки. Если найдена ссылка на TextBox, заголовок находится.

Обратите внимание, что вы не можете использовать item.Cells[x.Index].FindControl(txt.ID) с момента FindControl первых попыток найти NamingContainer элемента управления, который является GridViewRow/DataGridItem так это не помогает искать клетки.

Смежные вопросы