Cascading Combobox in DataGrid using DataTemplate Cross-Cell Binding

梦想的初衷 提交于 2019-12-25 04:47:09

问题


If I place my cascading comboboxes inside the same DataTemplate in a WPF DataGrid cell - the binding works properly (via ElementName). However, from a UI perspective I want my comboboxes to physically reside in different cells, not the same datagrid cell. How do you make cross-cell binding work (between DataTemplates) using DataGridTemplateColumns? It seems the issue is that the second comboboxes' ItemsSource cannot find the ElementName for binding when the comboboxes exist in different DataTemplate columns.

This works....

<DataGrid x:Name="grdItems" AutoGenerateColumns="false" ItemsSource="{Binding Model}">          
                <DataGrid.Columns>        
                    <DataGridTemplateColumn Header="Car Make / Model" Width="150">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <ComboBox x:Name="cbCarMake" SelectedItem="{Binding CarMake, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=DataContext.CarMakes, Mode=TwoWay}" DisplayMemberPath="Name" SelectedValuePath="ID">
                                    <i:Interaction.Triggers>
                                        <i:EventTrigger EventName="SelectionChanged">
                                            <mvvm:EventToCommand Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=DataContext.SelectCarMake}" PassEventArgsToCommand="True"/>
                                        </i:EventTrigger>
                                    </i:Interaction.Triggers>
                                </ComboBox>                            
                                <ComboBox SelectedItem="{Binding CarModel, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding ElementName=cbCarMake, Path=Tag.CarModels, Mode=TwoWay}" DisplayMemberPath="Name" SelectedValuePath="ID"/>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                </DataGrid.Columns>
     </DataGrid>

This doesn't....

 <DataGrid x:Name="grdItems" AutoGenerateColumns="false" ItemsSource="{Binding Model}">          
            <DataGrid.Columns>        
                <DataGridTemplateColumn Header="Car Make" Width="150">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox x:Name="cbCarMake" SelectedItem="{Binding CarMake, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=DataContext.CarMakes, Mode=TwoWay}" DisplayMemberPath="Name" SelectedValuePath="ID">
                                <i:Interaction.Triggers>
                                    <i:Interaction.Triggers>
                                        <i:EventTrigger EventName="SelectionChanged">
                                            <mvvm:EventToCommand Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=DataContext.SelectCarMake}" PassEventArgsToCommand="True"/>
                                        </i:EventTrigger>
                                    </i:Interaction.Triggers>
                                </i:Interaction.Triggers>
                            </ComboBox>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTemplateColumn Header="Car Model" Width="150">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox SelectedItem="{Binding CarModel, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding ElementName=cbCarMake, Path=Tag.CarModels, Mode=TwoWay}" DisplayMemberPath="Name" SelectedValuePath="ID"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
 </DataGrid>

回答1:


The trick with cross-data template binding is to use the ViewModel as a go-between. When properties change on the view model (an ObservableCollection in this case), you can trigger this notification to the dependent listeners (elements listening to PropertyChanged events).

The issue for me was that the View Model wasn't receiving the PropertyChanged notifications it should have been. I assumed that the mvvm-light ObservableObject automatically triggered PropertyChanged events for all properties.

You must use the mvvminpcset code snippet which explicitly raises property change events for the items in your ObservableCollection. Once the PropertyChanged events started firing, the ItemSource binding worked as seen below.

<DataGrid x:Name="grdItems" AutoGenerateColumns="false" ItemsSource="{Binding Model}">          
            <DataGrid.Columns>        
                <DataGridTemplateColumn Header="Car Make" Width="150">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox x:Name="cbCarMake" SelectedItem="{Binding CarMake, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=DataContext.CarMakes, Mode=TwoWay}" DisplayMemberPath="Name" SelectedValuePath="ID">                                
                            </ComboBox>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTemplateColumn Header="Car Model" Width="150">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox SelectedItem="{Binding CarModel, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding CarMake.CarModels}" DisplayMemberPath="Name" SelectedValuePath="ID"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
 </DataGrid>


来源:https://stackoverflow.com/questions/8728588/cascading-combobox-in-datagrid-using-datatemplate-cross-cell-binding

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!