基于多个条件的 WPF 绑定
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18547579/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF Binding on multiple criterias
提问by Tvd
In my MVVM, in view I have a DataGrid where I want to enable the row elements based on 2 criteria. DataGrid has checkbox in 1 col (that is bound to IsRowChecked property) and a header checkbox in another col. I want to enable the row element if 1) IsRowChecked is true AND 2) Header checkbox is selected.
在我的 MVVM 中,我有一个 DataGrid,我想在其中启用基于 2 个条件的行元素。DataGrid 在 1 列中具有复选框(绑定到 IsRowChecked 属性)和在另一个列中具有标题复选框。如果 1) IsRowChecked 为真并且 2) 选择了标题复选框,我想启用行元素。
Is this multiple criteria setting possible ?
是否可以设置多个标准?
XAML
XAML
<DataGrid ItemsSource="{Binding SiList, Mode=TwoWay}" Name="dgvSiSelection">
<DataGrid.Columns>
<DataGridCheckBoxColumn Binding="{Binding IsRowChecked, Mode=TwoWay}"/>
<DataGridTextColumn Header="" Binding="{Binding Header}" MinWidth="108" IsReadOnly="True"/>
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Text="Number of Chemicals" Grid.Column="0" />
</Grid>
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=NumberOfCases}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox IsEnabled="{Binding Path=IsRowChecked}" Text="{Binding Path=NumberOfCases, Mode=TwoWay}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
<!-- Value1 chkValue11-->
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="1" Text="Value1" IsEnabled="{Binding ElementName=chkValue11, Path=IsChecked}" />
<CheckBox Name="chkValue11" Grid.Column="0" Width="16" />
</Grid>
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Value1}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox IsEnabled="{Binding ElementName=chkValue11, Path=IsChecked}" Text="{Binding Path=Value1, Mode=TwoWay}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
<!-- Value2 chkValue12-->
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="1" Text="Value2" IsEnabled="{Binding ElementName=chkValue12, Path=IsChecked}" />
<CheckBox Name="chkValue12" Grid.Column="0" Width="16" />
</Grid>
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Value2}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox IsEnabled="{Binding ElementName=chkValue12, Path=IsChecked}" Text="{Binding Path=Value2, Mode=TwoWay}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
"Number of Chemicals" col need only single criteria binding which I could do. Value1 & Value2 needs 2 criteria i.e. of IsRowChecked and header checkbox selected. I could do with single, but can't get a way to implement 2 criteria's in these bindings.
“化学品数量”列只需要我可以做到的单一标准绑定。Value1 和 Value2 需要 2 个条件,即 IsRowChecked 和选中的标题复选框。我可以使用单个,但无法在这些绑定中实现 2 个标准。
How can I achieve this sort of binding ???
我怎样才能实现这种绑定???
Any help is highly appreciated.
任何帮助都受到高度赞赏。
Thanks
谢谢
回答by Athari
There're two ways to work with complex expressions on bindings: MultiBindingwith a converter and MultiDataTriggerwith specific cases. For your example, both work nicely.
有两种方法可以处理绑定上的复杂表达式:MultiBinding使用转换器和MultiDataTrigger使用特定情况。对于您的示例,两者都可以很好地工作。
1. MultiBinding
1. 多重绑定
This method works for virtually any case, but requires implementing converters (they can be reused, obviously).
这种方法几乎适用于任何情况,但需要实现转换器(显然它们可以重用)。
Create
AndConverterclass implementingIMultiValueConverterinterface. It needs to returntrueif all values passed to it are true (DependencyProperty.UnsetValueis a special value when value is not available).public class AndConverter : IMultiValueConverter { public object Convert (object[] values, Type targetType, object parameter, CultureInfo culture) { if (values.Any(v => ReferenceEquals(v, DependencyProperty.UnsetValue))) return DependencyProperty.UnsetValue; return values.All(System.Convert.ToBoolean); } public object[] ConvertBack (object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotSupportedException(); } }Add the converter to resources:
<Window.Resources> <local:AndConverter x:Key="convAnd"/> </Window.Resources>Specify
DataTemplateforValue1column (original code is commented):<DataTemplate DataType="local:Item"> <!--<TextBox IsEnabled="{Binding ElementName=chkValue11, Path=IsChecked}" Text="{Binding Path=Value1, Mode=TwoWay}"/>--> <TextBox Text="{Binding Path=Value1, Mode=TwoWay}"> <TextBox.IsEnabled> <MultiBinding Converter="{StaticResource convAnd}"> <Binding ElementName="chkValue11" Path="IsChecked"/> <Binding Path="IsRowChecked"/> </MultiBinding> </TextBox.IsEnabled> </TextBox> </DataTemplate>
创建
AndConverter类实现IMultiValueConverter接口。true如果传递给它的所有值都为真,它需要返回(DependencyProperty.UnsetValue当值不可用时是一个特殊值)。public class AndConverter : IMultiValueConverter { public object Convert (object[] values, Type targetType, object parameter, CultureInfo culture) { if (values.Any(v => ReferenceEquals(v, DependencyProperty.UnsetValue))) return DependencyProperty.UnsetValue; return values.All(System.Convert.ToBoolean); } public object[] ConvertBack (object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotSupportedException(); } }将转换器添加到资源:
<Window.Resources> <local:AndConverter x:Key="convAnd"/> </Window.Resources>DataTemplate为Value1列指定(原始代码已注释):<DataTemplate DataType="local:Item"> <!--<TextBox IsEnabled="{Binding ElementName=chkValue11, Path=IsChecked}" Text="{Binding Path=Value1, Mode=TwoWay}"/>--> <TextBox Text="{Binding Path=Value1, Mode=TwoWay}"> <TextBox.IsEnabled> <MultiBinding Converter="{StaticResource convAnd}"> <Binding ElementName="chkValue11" Path="IsChecked"/> <Binding Path="IsRowChecked"/> </MultiBinding> </TextBox.IsEnabled> </TextBox> </DataTemplate>
2. MultiDataTrigger
2. 多数据触发器
This method works when only one property value configuration needs specific behavior. In your example, the text box is always disabled, except when bothcheck boxes are checked. The syntax is more complex, but converters are not required.
当只有一个属性值配置需要特定行为时,此方法有效。在您的示例中,文本框始终处于禁用状态,除非同时选中两个复选框。语法更复杂,但不需要转换器。
Specify
DataTemplateforValue2column (original code is commented):<DataTemplate DataType="local:Item"> <!--<TextBox IsEnabled="{Binding ElementName=chkValue12, Path=IsChecked}" Text="{Binding Path=Value2, Mode=TwoWay}"/>--> <TextBox x:Name="txt" Text="{Binding Path=Value2, Mode=TwoWay}" IsEnabled="False"/> <DataTemplate.Triggers> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding IsChecked, ElementName=chkValue12}" Value="True"/> <Condition Binding="{Binding IsRowChecked}" Value="True"/> </MultiDataTrigger.Conditions> <Setter TargetName="txt" Property="IsEnabled" Value="True"/> </MultiDataTrigger> </DataTemplate.Triggers> </DataTemplate>
DataTemplate为Value2列指定(原始代码已注释):<DataTemplate DataType="local:Item"> <!--<TextBox IsEnabled="{Binding ElementName=chkValue12, Path=IsChecked}" Text="{Binding Path=Value2, Mode=TwoWay}"/>--> <TextBox x:Name="txt" Text="{Binding Path=Value2, Mode=TwoWay}" IsEnabled="False"/> <DataTemplate.Triggers> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding IsChecked, ElementName=chkValue12}" Value="True"/> <Condition Binding="{Binding IsRowChecked}" Value="True"/> </MultiDataTrigger.Conditions> <Setter TargetName="txt" Property="IsEnabled" Value="True"/> </MultiDataTrigger> </DataTemplate.Triggers> </DataTemplate>

