0

I have requirement on Nested datagrid in WPF. Parent Grid Shown Order information of Consumers.When User click the details in order information, need to be displayed ordered items details in child datagrid(Means Nested grid) within the parent row of order information. For this i am using <DataGrid.RowDetailsTemplate> to bind child datagrid. My XAML code is as follows.

<Popup Name="popup1" IsOpen="False" Placement="Mouse" Height="500" Width="700">                       
    <Border BorderBrush="Black" BorderThickness="1" Background="White">
        <StackPanel Orientation="Horizontal">                   
            <Grid>
               <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto" />

                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>                        
                <DataGrid Grid.Row="0" Grid.Column="0" SelectedValuePath="orderid" 
                          AutoGenerateColumns="False" Height="350"  
                          HorizontalAlignment="Left" Margin="114,128,0,0" x:Name="gridOrder" VerticalAlignment="Top" Width="500">
                    <DataGrid.Columns>                                
                        <DataGridTemplateColumn Header="Order Status">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <Button Content="{Binding OrderStatus}" Click="EditButton_Click" />                                            
                                </DataTemplate>                                        
                            </DataGridTemplateColumn.CellTemplate>                                    
                        </DataGridTemplateColumn>                                
                        <DataGridTextColumn Header="Full Name" Binding="{Binding fullname}" />
                        <DataGridTextColumn Header="Order ID" Binding="{Binding orderid}" />                                
                        <DataGridTextColumn Header="Mobile" Binding="{Binding mobile}" />
                        <DataGridTextColumn Header="No. of Items" Binding="{Binding countofItems}" />                                   
                        <DataGridTextColumn Header="Total Price" Binding="{Binding Total_Price}" />
                        <DataGridTextColumn Header="Order Status" Binding="{Binding OrderStatus}" />
                    </DataGrid.Columns> 
                    <DataGrid.RowDetailsTemplate>
                        <DataTemplate>
                            <DataGrid x:Name="gridOrderDetails"  AutoGenerateColumns="False" 
                                      Height="200" HorizontalAlignment="Left" Margin="121,132,0,0" VerticalAlignment="Top" Width="200">
                                <DataGrid.Columns>
                                    <DataGridTextColumn Header="Item ID" Binding="{Binding itemid}" />
                                    <DataGridTextColumn Header="Item Name" Binding="{Binding ItemName}" />
                                    <DataGridTextColumn Header="Item No." Binding="{Binding ItemNo}" />
                                    <DataGridTextColumn Header="Quantity" Binding="{Binding quantity}" />
                                    <DataGridTextColumn Header="Comments" Binding="{Binding comments}" />
                                    <DataGridTextColumn Header="Item Price" Binding="{Binding ItemPrice}" />
                                    <DataGridTextColumn Header="Quantity" Binding="{Binding quantity}" />
                                </DataGrid.Columns>
                            </DataGrid>

                        </DataTemplate>
                    </DataGrid.RowDetailsTemplate>
                </DataGrid>                       

                <Button Content="Close" Grid.Row="1" Grid.Column="1" Click="PopUp_OK_Click"/>
            </Grid>

        </StackPanel>
    </Border>
</Popup>

My C# code is as follows:

private void EditButton_Click(object sender, RoutedEventArgs e)
{
    try
    {
        DBDataContext dbContext = new DBDataContext();
        SP_Get_OrderItemResult orderRow = gridOrder.SelectedItem as SP_Get_OrderItemResult;                
        DataGrid grid = gridOrder.FindResource("gridOrderDetails") as DataGrid;                             
        grid.ItemsSource = dbContext.SP_Get_ItemList(orderRow.orderid); 
    }
    catch (Exception Ex)
    {
        MessageBox.Show(Ex.Message);
        return;
    }
}

I am unable to pass the orderid of gridOrder in FindResource(:gridOrderDetails").

DataGrid grid = gridOrder.FindResource("gridOrderDetails") as DataGrid;

Getting error at above line as 'gridOrderDetails' resource not found.

Yael
  • 1,566
  • 3
  • 18
  • 25
Hussain
  • 223
  • 1
  • 4
  • 18
  • Anyway, even if you were able to find the nested DataGrid, you're searching in your main DataGrid as a whole... What if several nested DataGrids are shown at the same time? – almulo Jul 01 '15 at 10:16
  • In main datagrid just showing order Information from order table. In child datagrid showing order item details, which is from another table OrderItemdetails table. – Hussain Jul 01 '15 at 10:29
  • I see. But you should make sure only one RowDetail is shown at any time. You should specify `SelectionMode="Single"`, or else your users would be able to open more than one RowDetail by selecting rows with Ctrl+click, for instance. – almulo Jul 01 '15 at 10:36

1 Answers1

1

That's because gridOrderDetails is not a Resource. Resources are defined as such in Resource dictionaries, gridOrderDetails is just a control inside a Template.

Try to use the function that answered this question instead:

private void EditButton_Click(object sender, RoutedEventArgs e)
{
    try
    {
        DBDataContext dbContext = new DBDataContext();
        SP_Get_OrderItemResult orderRow = gridOrder.SelectedItem as SP_Get_OrderItemResult;                
        DataGrid grid = FindChild<DataGrid>(gridOrder, "gridOrderDetails");                      
        grid.ItemsSource = dbContext.SP_Get_ItemList(orderRow.orderid); 
    }
    catch (Exception Ex)
    {
        MessageBox.Show(Ex.Message);
        return;
    }
}

/// <summary>
/// Finds a Child of a given item in the visual tree. 
/// </summary>
/// <param name="parent">A direct parent of the queried item.</param>
/// <typeparam name="T">The type of the queried item.</typeparam>
/// <param name="childName">x:Name or Name of child. </param>
/// <returns>The first parent item that matches the submitted type parameter. 
/// If not matching item can be found, 
/// a null parent is being returned.</returns>
public static T FindChild<T>(DependencyObject parent, string childName)
   where T : DependencyObject
{    
  // Confirm parent and childName are valid. 
  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);
    // If the child is not of the request child type child
    T childType = child as T;
    if (childType == null)
    {
      // recursively drill down the tree
      foundChild = FindChild<T>(child, childName);

      // If the child is found, break so we do not overwrite the found child. 
      if (foundChild != null) break;
    }
    else if (!string.IsNullOrEmpty(childName))
    {
      var frameworkElement = child as FrameworkElement;
      // If the child's name is set for search
      if (frameworkElement != null && frameworkElement.Name == childName)
      {
        // if the child's name is of the request name
        foundChild = (T)child;
        break;
      }
    }
    else
    {
      // child element found.
      foundChild = (T)child;
      break;
    }
  }

  return foundChild;
}
Community
  • 1
  • 1
almulo
  • 4,918
  • 1
  • 20
  • 29
  • Getting null for grid when i debug this code at DataGrid grid = LogicalTreeHelper.FindLogicalNode(gridOrder, "gridOrderDetails") as DataGrid; – Hussain Jul 01 '15 at 10:43
  • getting error "Object reference not set to an instance" while binding grid.ItemsSource because getting null while debuging at line DataGrid grid = LogicalTreeHelper.FindLogicalNode(gridOrder, "gridOrderDetails") as DataGrid; – Hussain Jul 01 '15 at 10:47
  • Ok... Try using the method on the answer to this question: http://stackoverflow.com/questions/636383/how-can-i-find-wpf-controls-by-name-or-type – almulo Jul 01 '15 at 10:51
  • Used the code as suggested, DataGrid grid = UIHelper.FindChild(Application.Current.MainWindow, "gridOrderDetails"); what is UIHelper method here? – Hussain Jul 01 '15 at 11:25
  • It's not a method, is the class where you put the FindChild method. In the example it was UIHelper, in my code I put it on the same class (so you can call it directly). It can be whatever you want. – almulo Jul 01 '15 at 11:41
  • Hi Almulo, here i have one more issue. In the event EditButton_Click the data is binding to gridOrderDetails using grid.ItemsSource. But it is not displaying exactly under corresponding to the parent grid. Only first two records showing child grid correctly. Can you please help this bug. – Hussain Jul 07 '15 at 12:06
  • You should create a new question and explain the problem there, in detail. Link back here if you want, so I can check it. – almulo Jul 07 '15 at 13:50
  • 1
    Posted as suggested separate question http://stackoverflow.com/questions/31294397/how-to-display-nested-datagrids-in-wpf . Please help – Hussain Jul 08 '15 at 13:37