1

I have three DataGrids set up as individual UserControls with each ItemsSource bound to a different DependencyProperty in my ViewModel. When a row is selected in the first DataGrid, the other two populate with information relevant to the selected row. Though this works fine, I want the second and third DataGrid to be displayed in the RowDetailsTemplate of the first DataGrid.

The issue I am having is that the ItemsSource of the parent DataGrid is overriding that of the other two, so they are not populating. I have tried solutions posted on many other similar questions but none have solved my problem. My code is below, I'm hoping that I've just missed something obvious but any help would be appreciated!

Main Datagrid

<DataGrid x:Name="PostDataGrid" 
              ItemsSource="{Binding WSEDriverList}" 
              SelectedItem="{Binding SelectedWSEDriverPOST}"
              Style="{DynamicResource MainDataGridStyle}"
              Margin="0,0,0,0"
              Grid.Row="1" >
        <DataGrid.Columns>
            <DataGridTextColumn  Header="HesId"             Binding="{Binding HESID,            Mode=OneWay}"                 Width="50"/>
            <DataGridTextColumn  Header="WseId"             Binding="{Binding WSEID,            Mode=OneWay}"                 Width="50"/>
            <DataGridTextColumn  Header="API"               Binding="{Binding API,              Mode=OneWay}"                 Width="198" />
            <DataGridTextColumn  Header="Request Date"      Binding="{Binding Path=REQUEST_DATE, Mode=OneWay, StringFormat=dd/MM/yyyy HH:mm:ss}" Width="125"/>
            <DataGridTextColumn  Header="Result Date"       Binding="{Binding Path=RESULT_DATE,  Mode=OneWay, StringFormat=dd/MM/yyyy HH:mm:ss}" Width="125"/>
            <DataGridTextColumn  Header="Return Code"       Binding="{Binding RETURN_CODE,      Mode=OneWay,  StringFormat=0}" Width="80" />
            <DataGridTextColumn  Header="Status"            Binding="{Binding STATUS,           Mode=OneWay,  StringFormat=0}" Width="70" />
        </DataGrid.Columns>
        <DataGrid.RowDetailsTemplate>
            <DataTemplate DataType="{x:Type viewmodel:WSEAuditViewModel}">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="*"/>
                        <RowDefinition Height="*"/>
                    </Grid.RowDefinitions>
                    <Expander Header="NOTIFICATION" Grid.Row="0">
                        <ItemsControl ItemsSource="{Binding WSEDriverGETResult}">
                            <usercontrol:NOTIFICATIONUserControl/>
                        </ItemsControl>
                    </Expander>
                    <Expander Header="GET" Grid.Row="1">
                        <ItemsControl ItemsSource="{Binding WSEDriverGETResult}">
                            <usercontrol:GETUserControl/>
                        </ItemsControl>
                    </Expander>
                </Grid>
            </DataTemplate>
        </DataGrid.RowDetailsTemplate>
    </DataGrid>

DataGrid 2 (NOTIFICATIONUserControl)

<DataGrid x:Name="NotificationDG" 
              ItemsSource="{Binding NotificationResult}" 

DataGrid 3 (GETUserControl)

<DataGrid x:Name="GetDG" 
              ItemsSource="{Binding WSEDriverGETResult}" 

Edit

Here is the code for my DependencyProperties bound to my DataGrid.

//----POST result list from WSE_DRIVER-----
    public List<WSE_DRIVER> WSEDriverList
    {
        get { return (List<WSE_DRIVER>)GetValue(WSEDriverListProperty); }
        set { SetValue(WSEDriverListProperty, value); }
    }

    public static readonly DependencyProperty WSEDriverListProperty =
        DependencyProperty.Register("WSEDriverList",
                                    typeof(List<WSE_DRIVER>),
                                    typeof(WSEAuditViewModel),
                                    new PropertyMetadata(WSEDriverListChanged_Callback));

    private static void WSEDriverListChanged_Callback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        WSEAuditViewModel wse_win = (WSEAuditViewModel)d;
        if (wse_win.WSEDriverList.Count > 0)
        {
            wse_win.SelectedWSEDriverPOST = wse_win.WSEDriverList.First();
        }

    }

    //----Selected POST WSE_Driver----
    public WSE_DRIVER SelectedWSEDriverPOST
    {
        get { return (WSE_DRIVER)GetValue(SelectedWSEDriverPOSTProperty); }
        set { SetValue(SelectedWSEDriverPOSTProperty, value); }
    }

    public static readonly DependencyProperty SelectedWSEDriverPOSTProperty =
        DependencyProperty.Register("SelectedWSEDriverPOST",
                                    typeof(WSE_DRIVER),
                                    typeof(WSEAuditViewModel),
                                    new PropertyMetadata(SelectedWSEDriverPOSTChanged_Callback));

    private static void SelectedWSEDriverPOSTChanged_Callback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
          //Gets list and assigns to WSEDriverGETResult and NotificationResult
    }



    //----GET result from WSE_Driver----
    public List<WSE_DRIVER> WSEDriverGETResult
    {
        get { return (List<WSE_DRIVER>)GetValue(WSEDriverGETResultProperty); }
        set { SetValue(WSEDriverGETResultProperty, value); }
    }

    public static readonly DependencyProperty WSEDriverGETResultProperty =
        DependencyProperty.Register("WSEDriverGETResult",
                                    typeof(List<WSE_DRIVER>),
                                    typeof(WSEAuditViewModel),
                                    new PropertyMetadata(WSEDriverGETResultChanged_Callback));

    private static void WSEDriverGETResultChanged_Callback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {

    }



    //----Notification Info----
    public List<SPEC_NOTIFICATION> NotificationResult
    {
        get { return (List<SPEC_NOTIFICATION>)GetValue(NotificationResultProperty); }
        set { SetValue(NotificationResultProperty, value); }
    }

    public static readonly DependencyProperty NotificationResultProperty =
        DependencyProperty.Register("NotificationResult",
                                    typeof(List<SPEC_NOTIFICATION>),
                                    typeof(WSEAuditViewModel),
                                    new UIPropertyMetadata(NotificationResultChanged_Callback));

    private static void NotificationResultChanged_Callback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
    }
GDiff94
  • 137
  • 1
  • 2
  • 8
  • So where is the NotificationResult property defined? – mm8 May 23 '17 at 10:48
  • My dependency properties have callbacks that deal with the selection change (I am new to wpf so assuming that's what you mean?) – GDiff94 May 23 '17 at 11:03
  • Post your code if you want anyone to be able to help you. You are trying to bind to some property called NotificationResult. How is anyone supposed to know anything about this property? – mm8 May 23 '17 at 11:17
  • Apologies, I mis-read your comment. Will update with the full code. – GDiff94 May 23 '17 at 11:26

1 Answers1

1

Since the NotificationResult and WSEDriverGETResult properties belong to the same class as the WSEDriverList property, you should be able to use a {RelativeSource} to bind to the DataContext of the parent DataGrid:

<DataGrid x:Name="NotificationDG" ItemsSource="{Binding DataContext.NotificationResult, 
            RelativeSource={RelativeSource AncestorType=DataGrid}}"></DataGrid>

<DataGrid x:Name="GetDG" ItemsSource="{Binding DataContext.WSEDriverGETResult, 
            RelativeSource={RelativeSource AncestorType=DataGrid}}"></DataGrid>
mm8
  • 163,881
  • 10
  • 57
  • 88
  • Thank you! I tried something very similar before but I set the AncestorType as UserControl instead! – GDiff94 May 23 '17 at 12:30
  • The reference structure worked well. I had tried an acestor of UserControl and DataGird, but eventually what worked was DataGridRow. ` ` – Galactic May 12 '20 at 12:51