How do I access the items of DataGrid in Datagrid row detail by name in WPF?

Mojtaba_Hakim 281 Reputation points
2022-06-24T15:08:19.69+00:00

I use C# WPF I want to display data in Nested DataGrid , like this simulation ↓

What I need : 214891-last.gif

The problem is I cannot access the DataGrid in RowDetail of the Main DataGrid by the name !

What have I try:

XAML :

    <Grid>  
    <DataGrid x:Name="MainDGR1" Visibility="Visible" ItemsSource="{Binding Employees}" SelectedItem="{Binding SelectedEmployee}" Loaded="MainDGR1_Loaded" >  
        <DataGrid.RowHeaderTemplate>  
            <DataTemplate>  
                <Expander Expanded="Expander_Expanded" Height="20" Collapsed="Expander_Collapsed" Header="جزئیات" >  
                </Expander>  
            </DataTemplate>  
        </DataGrid.RowHeaderTemplate>  
  
        <DataGrid.RowDetailsTemplate>  
            <DataTemplate>  
                <DataGrid x:Name="DetailDGR2" ItemsSource="{Binding Details}"/>  
            </DataTemplate>  
        </DataGrid.RowDetailsTemplate>  
    </DataGrid>  
</Grid>  

Code Behind :

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Threading.Tasks;  
using System.Windows;  
using System.Windows.Controls;  
using System.Windows.Data;  
using System.Windows.Documents;  
using System.Windows.Input;  
using System.Windows.Media;  
using System.Windows.Media.Imaging;  
using System.Windows.Navigation;  
using System.Windows.Shapes;  
  
namespace WpfApp60  
{  
    public partial class MainWindow : Window  
    {  
        public MainWindow()  
        {  
            InitializeComponent();  
  
            var detail1 = new EmployeeDetails() { ManagerID = 11, ManagerName = "11 Ali", ManagerMobile = "123456" };  
            var detail2 = new EmployeeDetails() { ManagerID = 12, ManagerName = "12 Name", ManagerMobile = "123456" };  
            var detail3 = new EmployeeDetails() { ManagerID = 13, ManagerName = "13 Name", ManagerMobile = "123456" };  
  
            var detail4 = new EmployeeDetails() { ManagerID = 11, ManagerName = "11 Ali", ManagerMobile = "123456" };  
            var detail5 = new EmployeeDetails() { ManagerID = 12, ManagerName = "12 Name", ManagerMobile = "123456" };  
            var detail6 = new EmployeeDetails() { ManagerID = 13, ManagerName = "13 Name", ManagerMobile = "123456" };  
  
            var detail7 = new EmployeeDetails() { ManagerID = 11, ManagerName = "11 Ali", ManagerMobile = "123456" };  
            var detail8 = new EmployeeDetails() { ManagerID = 12, ManagerName = "12 Name", ManagerMobile = "123456" };  
            var detail9 = new EmployeeDetails() { ManagerID = 13, ManagerName = "13 Name", ManagerMobile = "123456" };  
  
            var details1 = new List<EmployeeDetails>();  
            details1.Add(detail1);  
            details1.Add(detail2);  
            details1.Add(detail3);  
  
            var details2 = new List<EmployeeDetails>() { detail4, detail5, detail6 };  
            var details3 = new List<EmployeeDetails>() { detail7, detail8, detail9 };  
  
            Employees = new List<Employee>();  
            Employees.Add(new Employee() { ID = 1, Name = "Name1", Details = details1 });  
            Employees.Add(new Employee() { ID = 2, Name = "Name2", Details = details2 });  
            Employees.Add(new Employee() { ID = 3, Name = "Name3", Details = details3 });  
  
            SelectedEmployee = Employees[1];  
  
            this.DataContext = this;  
        }  
        public List<Employee> Employees { get; set; }  
        private Employee _selected;  
        public Employee SelectedEmployee  
        {  
            get { return _selected; }  
            set { _selected = value; }  
        }  
        #region ExpandOnClick  
        private void Expander_Expanded(object sender, RoutedEventArgs e)  
        {  
            for (var vis = sender as Visual; vis != null; vis = VisualTreeHelper.GetParent(vis) as Visual)  
                if (vis is DataGridRow)  
                {  
                    var row = (DataGridRow)vis;  
                    row.DetailsVisibility = row.DetailsVisibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;  
                    break;  
                }  
        }  
  
        private void Expander_Collapsed(object sender, RoutedEventArgs e)  
        {  
            for (var vis = sender as Visual; vis != null; vis = VisualTreeHelper.GetParent(vis) as Visual)  
                if (vis is DataGridRow)  
                {  
                    var row = (DataGridRow)vis;  
                    row.DetailsVisibility = row.DetailsVisibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;  
                    break;  
                }  
        }  
        #endregion  
  
        private void MainDGR1_Loaded(object sender, RoutedEventArgs e)  
        {  
            var MyControl = this.FindName("DetailDGR2"); // ← The result will be null !  
            //DetailDGR2  
  
        }  
    }  
    public class Employee  
    {  
        public int ID { get; set; }  
        public string Name { get; set; }  
        public List<EmployeeDetails> Details { get; set; }  
    }  
    public class EmployeeDetails  
    {  
        public int ManagerID { get; set; }  
        public string ManagerName { get; set; }  
        public string ManagerMobile { get; set; }  
  
    }  
}  

My Problem: interestingly, the compiler does not find the name of this control!

214839-123.png

how can I access the items of that DataGrid in row detail by x:Name ?

please help

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,678 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,286 questions
Visual Studio Debugging
Visual Studio Debugging
Visual Studio: A family of Microsoft suites of integrated development tools for building applications for Windows, the web and mobile devices.Debugging: The act or process of detecting, locating, and correcting logical or syntactical errors in a program or malfunctions in hardware. In hardware contexts, the term troubleshoot is the term more frequently used, especially if the problem is major.
943 questions
XAML
XAML
A language based on Extensible Markup Language (XML) that enables developers to specify a hierarchy of objects with a set of properties and logic.
766 questions
0 comments No comments
{count} votes

Accepted answer
  1. Hui Liu-MSFT 40,271 Reputation points Microsoft Vendor
    2022-06-27T02:58:53.283+00:00

    For accessing the controls in the DataTemplate, you could try the code below.
    Xaml:

     <Window.DataContext>  
            <local:ViewModel/>  
        </Window.DataContext>  
        <StackPanel>  
            <DataGrid Name="dg1" AutoGenerateColumns="False" SelectionMode="Single" CanUserAddRows="false"   
                      CanUserDeleteRows="False" SelectionUnit="FullRow" ItemsSource="{Binding View}" >  
                <DataGrid.CellStyle>  
                    <Style TargetType="DataGridCell">  
                        <Setter Property="BorderThickness" Value="0"/>  
                    </Style>  
                </DataGrid.CellStyle>  
                <DataGrid.RowHeaderTemplate>  
                    <DataTemplate>  
                        <Expander Expanded="Expander_Expanded" Collapsed="Expander_Collapsed">  
                        </Expander>  
                    </DataTemplate>  
                </DataGrid.RowHeaderTemplate>  
                <DataGrid.Columns>  
                    <DataGridTextColumn Header="ID" IsReadOnly="True" Width="100" Binding="{Binding ID}" />  
                    <DataGridTextColumn Header="Name" IsReadOnly="True" Width="100" Binding="{Binding Name}" />  
                </DataGrid.Columns>  
                <DataGrid.RowDetailsTemplate>  
                    <DataTemplate>  
                        <DataGrid x:Name="dg" ItemsSource="{Binding Details}" Initialized="dg_Initialized"  >  
                            <DataGrid.Columns>  
                                <DataGridTextColumn  IsReadOnly="True" Width="100" Binding="{Binding Title}" />  
                                <DataGridTextColumn Header="Address" IsReadOnly="True" Width="100" Binding="{Binding Address}" />  
                            </DataGrid.Columns>  
                        </DataGrid>  
                    </DataTemplate>  
                </DataGrid.RowDetailsTemplate>  
            </DataGrid>  
      
        </StackPanel>  
    

    Codebehind:

     public partial class MainWindow : Window  
      {  
       
        public MainWindow()  
        {  
          InitializeComponent();  
      
        }  
        private void Expander_Expanded(object sender, RoutedEventArgs e)  
        {  
          for (var vis = sender as Visual; vis != null; vis = VisualTreeHelper.GetParent(vis) as Visual)  
            if (vis is DataGridRow)  
            {  
              var row = (DataGridRow)vis;  
              row.DetailsVisibility = row.DetailsVisibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;  
              break;  
            }  
      
           
        }  
      
        private void Expander_Collapsed(object sender, RoutedEventArgs e)  
        {  
          for (var vis = sender as Visual; vis != null; vis = VisualTreeHelper.GetParent(vis) as Visual)  
            if (vis is DataGridRow)  
            {  
              var row = (DataGridRow)vis;  
              row.DetailsVisibility = row.DetailsVisibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;  
              break;  
            }  
        }  
        public IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject  
        {  
          if (depObj != null)  
          {  
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)  
            {  
              DependencyObject child = VisualTreeHelper.GetChild(depObj, i);  
      
              if (child != null && child is T)  
                yield return (T)child;  
      
              foreach (T childOfChild in FindVisualChildren<T>(child))  
                yield return childOfChild;  
            }  
          }  
        }  
      
        private void dg_Initialized(object sender, System.EventArgs e)  
        {  
          foreach (var datagrid in FindVisualChildren<DataGrid>(this))  
          {  
            if (datagrid.Name == "dg")  
            {  
               
              datagrid.Columns[0].Header = "MyTitle";  
              datagrid.AutoGenerateColumns=false;  
              datagrid.CanUserAddRows = true;  
              datagrid. CanUserDeleteRows =true;  
            }  
          }  
        }  
      }  
    

    The result:
    215118-image.png


    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

1 additional answer

Sort by: Most helpful
  1. Ken Tucker 5,846 Reputation points
    2022-06-25T12:21:32.57+00:00

    The short answer is you can not. You can however bind the DetailsVisibility to any property in your datasource and use a class that Inherits from IValueConverter to convert the propery value to a visibility

    https://learn.microsoft.com/en-us/dotnet/api/system.windows.data.ivalueconverter?view=windowsdesktop-6.0

    0 comments No comments