Search code examples
wpflistviewdata-bindingbindingdatatemplate

Dynamically bind listview to corresponding datagrid row


I have a listview inside the datagrid, however I'm having trouble assigning item source that is dependent on the id of the ItemsSource="{Binding Users}". In other words I am trying to get each list view to only show data that is corresponding to the id. i currently have loop that will gather a DataSet of data for the user, im just having trouble binding each DataSet.

<DataGrid Name="dgUsers" ItemsSource="{Binding Users}">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Client" Binding="{Binding Name}"/>
          <!--  <DataGridTextColumn Header="Land Line" Binding="{Binding LandLine}"/>    -->     
        </DataGrid.Columns>
        <DataGrid.RowDetailsTemplate>
            <DataTemplate x:Name="datatemplate">
                <DockPanel Background="GhostWhite">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="200"/>
                            <ColumnDefinition Width="200"/>
                            <ColumnDefinition/>
                        </Grid.ColumnDefinitions>

                         <ListView x:Name="lvData" Margin="10,82,10,156" Grid.Column="2" ItemsSource="{Binding view }" SelectedValue="{Binding selectedValue}" MouseDoubleClick="LoadSelectedData" >
                            <ListView.View>
                                <GridView>
                                    <GridViewColumn Width="150" DisplayMemberBinding="{Binding type}">
                                        <GridViewColumnHeader Tag="type" Content="Type" FontSize="12"/>
                                    </GridViewColumn>
                                    <GridViewColumn Width="150" DisplayMemberBinding="{Binding source}">
                                        <GridViewColumnHeader Tag="source" Content="Source" FontSize="12"/>
                                    </GridViewColumn>
                                    <GridViewColumn Width="180" DisplayMemberBinding="{Binding stage}">
                                        <GridViewColumnHeader Tag="stage"  Content="Stage" FontSize="12"/>
                                    </GridViewColumn>


                                </GridView>
                            </ListView.View>
                        </ListView>

Solution

  • If I understand correctly what you're doing -- each User has a list of properties -- the usual way to do this would be to put a pre-filtered collection of property items on each User item in the datagrid, then bind that to the ListView in the RowDetailsTemplate. The DataContext inside that DataTemplate will be some instance of the User class, so if that collection of user properties is User.dataForUser, you'd just bind like so:

    <ListView ItemsSource="{Binding dataForUser}" ... />
    

    And that should do it.

    You could also write a multi-value converter and use that with a multi-binding that binds both the full collection, and the user ID to filter the desired subset of items in the collection. The converter would do the filtering and return a List<SomeUserPropertyClass>. No need to make it an ObservableCollection, since you won't be making any changes to it after IMultiDataConverter.Convert() returns it. But binding to the full collection would mean some kind of RelativeSource binding to get that property from the main viewmodel. Lots of extra noise in your XAML.

    In my view, building this master-detail relationship into the viewmodel classes is both appropriate and convenient.