[英]MultiBinding with two Comboboxes in different DataContexts
我有以下数据网格,其中包含两个组合框,每个组合框都包含在数据模板中。
<DataGrid x:Name="FilterSelection" HorizontalAlignment="Stretch">
<DataGrid.Resources>
<DataTemplate x:Key="EntityComboboxTemp">
<ComboBox x:Name="EntityCombobox"
ItemsSource="{Binding DataContext.FilterVehicleEntities, RelativeSource={RelativeSource AncestorType=local:ExportView}}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction
Command="{Binding DataContext.SelectedEntityCommand, RelativeSource={RelativeSource AncestorType=local:ExportView}}"
CommandParameter="{Binding ElementName=EntityCombobox, Path=SelectedItem}">
</i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
</DataTemplate>
<DataTemplate x:Key="AttributeComboboxTemp">
<ComboBox x:Name="AttributeCombobox"
ItemsSource="{Binding DataContext.FilterAttributes, RelativeSource={RelativeSource AncestorType=local:ExportView}}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction
Command="{Binding DataContext.SelectedAttributeCommand, RelativeSource={RelativeSource AncestorType=local:ExportView}}">
<i:InvokeCommandAction.CommandParameter>
<MultiBinding Converter="{conv:FilterMultipleConverter}">
<Binding ElementName="EntityCombobox" Path="SelectedItem"/>
<Binding ElementName="AttributeCombobox" Path="SelectedItem"/>
</MultiBinding>
</i:InvokeCommandAction.CommandParameter>
</i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
</DataTemplate>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Entity" CellTemplate="{StaticResource EntityComboboxTemp}" />
<DataGridTemplateColumn Header="Entity Attribute" CellTemplate="{StaticResource AttributeComboboxTemp}"/>
</DataGrid.Columns>
</DataGrid>
问题在于第二个组合框的多重绑定,即该行:
Binding ElementName="EntityCombobox" Path="SelectedItem"/>
它将第一个组合框的选择项绑定到第二个组合框作为命令参数。 但是我总是会收到EntityCombobox未知的数据绑定错误。 我如何为该绑定设置DataContext,这甚至可能吗?
我的建议是不要做太多您认为的事情。 我建议在DataGrid的ViewModel中执行此逻辑。
首先,我将创建一个视图模型来保存您的过滤器选择。
示例:(请参阅注释,将选择更改的逻辑放在何处)
public class FilterViewModel
{
private string _vehicleEntity;
public string VehicleEntity
{
get { return _vehicleEntity; }
set
{
_vehicleEntity = value;
//OnPropertyChanged() if you want
}
}
private string _attribute;
public string Attribute
{
get { return _attribute; }
set
{
_attribute = value;
//Add logic here to determine what to do with both Attribute and VehicleEntity
//OnPropertyChanged() if you want
}
}
}
然后设置整个View的ViewModel,以保存FilterModel
的集合以及Vehicle选项和Attribute选项的列表。
例:
public class MainWindowViewModel
{
public ObservableCollection<FilterViewModel> Rows { get; }
public ObservableCollection<string> FilterVehicleEntities { get; }
public ObservableCollection<string> FilterAttributes { get; set; }
public MainWindowViewModel()
{
Rows = new ObservableCollection<FilterViewModel>();
FilterVehicleEntities = new ObservableCollection<string>()
{
"Vehicle 1",
"Vehicle 2",
"Vehicle 3",
};
FilterAttributes = new ObservableCollection<string>()
{
"Attribute 1",
"Attribute 2",
"Attribute 3",
};
}
}
然后,仅将选择内容直接绑定到属性,就可以减少视图的复杂性。 属性更新后,您将立即收到有关选择更改的通知(如FilterViewModel的注释中所标记)。
示例(完整的xaml):
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow"
Width="600"
Height="500">
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Grid>
<DataGrid
AutoGenerateColumns="False"
ItemsSource="{Binding Rows}">
<DataGrid.Columns>
<DataGridComboBoxColumn
Header="Entity"
SelectedItemBinding="{Binding VehicleEntity, UpdateSourceTrigger=PropertyChanged}">
<!-- property changed so we get the change right after we select-->
<DataGridComboBoxColumn.ElementStyle>
<Style
TargetType="ComboBox">
<Setter
Property="ItemsSource"
Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.FilterVehicleEntities}" />
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style
TargetType="ComboBox">
<Setter
Property="ItemsSource"
Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.FilterVehicleEntities}" />
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
<DataGridComboBoxColumn
Header="Entity Attribute"
SelectedItemBinding="{Binding Attribute, UpdateSourceTrigger=PropertyChanged}">
<!-- property changed so we get the change right after we select-->
<DataGridComboBoxColumn.ElementStyle>
<Style
TargetType="ComboBox">
<Setter
Property="ItemsSource"
Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.FilterAttributes}" />
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style
TargetType="ComboBox">
<Setter
Property="ItemsSource"
Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.FilterAttributes}" />
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
一个ComboBox
在一个DataTemplate
不能引用一个ComboBox
被定义在其他地方使用ElementName
约束力的,因为它们不是在同一个名称范围 。
您应该做的是将EntityCombobox
的SelectedItem
属性绑定到源属性,然后将另一个ComboBox
的CommandParameter
属性绑定到相同的源属性。 为此,定义source属性的类必须实现INotifyPropertyChanged
接口并引发更改通知,并且两个ComboBoxes
还必须共享相同的DataContext
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.