使用 DataTemplate 跨单元格绑定在 DataGrid 中级联组合框

发布于 2024-12-24 02:28:21 字数 4342 浏览 3 评论 0原文

如果我将级联组合框放置在 WPF DataGrid 单元格中的同一个 DataTemplate 内,则绑定可以正常工作(通过 ElementName)。然而,从用户界面的角度来看,我希望我的组合框物理上驻留在不同的单元格中,而不是同一个数据网格单元格中。如何使用 DataGridTemplateColumns 进行跨单元格绑定(DataTemplates 之间)?问题似乎是,当组合框存在于不同的 DataTemplate 列中时,第二个组合框的 ItemsSource 无法找到用于绑定的 ElementName

这有效......

<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>

这不......

 <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>

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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

半窗疏影 2024-12-31 02:28:21

跨数据模板绑定的技巧是使用 ViewModel 作为中间人。当视图模型上的属性发生更改(本例中为 ObservableCollection)时,您可以向依赖侦听器(侦听 PropertyChanged 事件的元素)触发此通知>)。

对我来说,问题是视图模型没有收到应有的 PropertyChanged 通知。我假设 mvvm-light ObservableObject 自动触发所有属性的 PropertyChanged 事件。

您必须使用 mvvminpcset 代码片段,该代码片段显式引发 ObservableCollection 中项目的属性更改事件。一旦 PropertyChanged 事件开始触发,ItemSource 绑定就会如下所示工作。

<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>

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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文