To find a control in a column of a DataGrid template, you must use FindChild() :
public static T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject { if (parent == null) { return null; } T foundChild = null; int childrenCount = VisualTreeHelper.GetChildrenCount(parent); for (int i = 0; i < childrenCount; i++) { var child = VisualTreeHelper.GetChild(parent, i); T childType = child as T; if (childType == null) { foundChild = FindChild<T>(child, childName); if (foundChild != null) break; } else if (!string.IsNullOrEmpty(childName)) { var frameworkElement = child as FrameworkElement; if (frameworkElement != null && frameworkElement.Name == childName) { foundChild = (T)child; break; } else { foundChild = FindChild<T>(child, childName); if (foundChild != null) { break; } } } else { foundChild = (T)child; break; } } return foundChild; }
For example, I have this template column in MyDataGrid :
<DataGridTemplateColumn Width="1.5*" IsReadOnly="False"> <DataGridTemplateColumn.Header> <TextBlock Text="Sample" ToolTip="{Binding Path=Text, RelativeSource={RelativeSource Self}}" FontSize="14" /> </DataGridTemplateColumn.Header> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock x:Name="MyTextBlock" Text="Hello!" /> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn>
Access this code, you can:
TextBlock MyTextBlock = FindChild<TextBlock>(MyDataGrid, "MyTextBlock"); MessageBox.Show(MyTextBlock.Text);
Note. Always use FindChild only when the control is fully loaded, otherwise it will not find it and will not give a null value. In this case, I put this code in the ContentRendered event (window), which says that all the contents of the window were successfully loaded (even the MyDataGrid_Loaded event does not have access to MyTextBlock, because it has not yet been loaded):
private void Window_ContentRendered(object sender, EventArgs e) { TextBlock MyTextBlock = FindChild<TextBlock>(MyDataGrid, "MyTextBlock"); MessageBox.Show(MyTextBlock.Text); }
EDIT1:
To access the selected row control to add the SelectionChanged event to the DataGrid , in which a function will be executed that will give the selected row:
private void MyDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e) { try { var row_list = GetDataGridRows(MyDataGrid); foreach (DataGridRow single_row in row_list) { if (single_row.IsSelected == true) { TextBlock MyTextBlock = FindChild<TextBlock>(single_row, "MyTextBlock"); MessageBox.Show(MyTextBlock.Text); } } } catch { throw new Exception("Can't get access to DataGridRow"); } }
List of GetDataGridRows ():
public IEnumerable<DataGridRow> GetDataGridRows(DataGrid grid) { var itemsSource = grid.ItemsSource as IEnumerable; if (null == itemsSource) { yield return null; } foreach (var item in itemsSource) { var row = grid.ItemContainerGenerator.ContainerFromItem(item) as DataGridRow; if (null != row) { yield return row; } } }
EDIT2:
To get ALL the elements, I rewrote the FindChild () function:
public static void FindChildGroup<T>(DependencyObject parent, string childName, ref List<T> list) where T : DependencyObject { // Checks should be made, but preferably one time before calling. // And here it is assumed that the programmer has taken into // account all of these conditions and checks are not needed. //if ((parent == null) || (childName == null) || (<Type T is not inheritable from FrameworkElement>)) //{ // return; //} int childrenCount = VisualTreeHelper.GetChildrenCount(parent); for (int i = 0; i < childrenCount; i++) { // Get the child var child = VisualTreeHelper.GetChild(parent, i); // Compare on conformity the type T child_Test = child as T; // Not compare - go next if (child_Test == null) { // Go the deep FindChildGroup<T>(child, childName, ref list); } else { // If match, then check the name of the item FrameworkElement child_Element = child_Test as FrameworkElement; if (child_Element.Name == childName) { // Found list.Add(child_Test); } // We are looking for further, perhaps there are // children with the same name FindChildGroup<T>(child, childName, ref list); } } return; }
Call this new function:
private void Window_ContentRendered(object sender, EventArgs e) { // Create the List List<TextBlock> list = new List<TextBlock>(); // Find all elements FindChildGroup<TextBlock>(MyDataGrid, "MyTextBlock", ref list); string text = ""; // Print foreach (TextBlock elem in list) { text += elem.Text + "\n"; } MessageBox.Show(text, "Text in TextBlock"); }
As a rule, this practice is not the best ... to get elements (such as all or selected), you can directly contact the list in which your data is stored (for example, ObservableCollection ). Also, these are useful events like PropertyChanged.