wpf 使用 OR 而不是 AND 的 MultiDataTrigger
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38396419/
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
MultiDataTrigger with OR instead of AND
提问by CBreeze
I am trying to set multiple DataTriggerson my Button. I did some research and found that MultiDataTriggerallows you to do this. I want the Visibilityproperty of my Buttonto be set to false if the CCTVPath == string.EmptyOR PermissionsFlag == false. This is what I have so far;
我正在尝试DataTriggers在我的Button. 我做了一些研究,发现可以MultiDataTrigger让你做到这一点。我希望Visibilitymy的属性Button设置为 false 如果CCTVPath == string.EmptyOR PermissionsFlag == false. 这是我到目前为止所拥有的;
<Button Grid.Column="3" x:Name="cctvFeedButton" Content="Live Feed"
Width="100" FontSize="16" HorizontalAlignment="Right" Margin="5" Click="OnCCTVButtonClick">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding CCTVPath}" Value=""/>
<Condition Binding="{Binding PermissionsFlag}" Value="False"/>
</MultiDataTrigger.Conditions>
<Setter Property="Visibility" Value="Hidden"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
And in my code-behind I set PermissionsFlaglike so;
在我的代码隐藏中,我PermissionsFlag是这样设置的;
public bool PermissionsFlag { get; set; }
private void OnPageLoaded(object sender, RoutedEventArgs e)
{
PermissionsFlag = false;
}
As you can see PermissionsFlagis definitely false, and the there are definitely empty CCTVPathhowever the Buttonis never hidden. What am I doing wrong?
正如你所看到PermissionsFlag的肯定是假的,那里肯定是空的,CCTVPath但Button永远不会隐藏。我究竟做错了什么?
UPDATE:
更新:
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private bool _permissionsFlag;
public bool Flag
{
get { return _permissionsFlag; }
set
{
_permissionsFlag = value;
OnPropertyChanged("PermissionsFlag");
}
}
private void OnPageLoaded(object sender, RoutedEventArgs e)
{
Flag = false;
CCTVImageCollection = GetImages();
imageListBox.ItemsSource = CCTVImageCollection;
DataContext = this;
}
In my XAML:
在我的 XAML 中:
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding PermissionsFlag}" Value="False">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
回答by ASh
tranform Conditions into two independent DataTriggers
将条件转换为两个独立的 DataTriggers
<Style.Triggers>
<DataTrigger Binding="{Binding CCTVPath}" Value="">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
<DataTrigger Binding="{Binding PermissionsFlag}" Value="False">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
</Style.Triggers>
make sure that binding paths are correct (check VS Output window for possible exception messages)
确保绑定路径正确(检查 VS 输出窗口以获取可能的异常消息)
另外:不要只依赖Button的隐藏状态,在代码中正确实现权限(
OnCCTVButtonClickOnCCTVButtonClick)。在这里阅读原因:How to Snoop proof your wpf application?
auto-property PermissionsFlag (public bool PermissionsFlag { get; set; }) doesn't notify view about changes.
auto-property PermissionsFlag ( public bool PermissionsFlag { get; set; }) 不会通知视图有关更改。
it is possible to implement INotifyPropertyChangedinterface (in my test window it is done like this: public partial class Window3 : Window, INotifyPropertyChanged) and then raise event when property changes.
可以实现INotifyPropertyChanged接口(在我的测试窗口中它是这样完成的:)public partial class Window3 : Window, INotifyPropertyChanged然后在属性更改时引发事件。
here is a complete working example which I used for test
这是我用于测试的完整工作示例
public partial class Window3 : Window, INotifyPropertyChanged
{
public Window3()
{
InitializeComponent();
this.DataContext = this;
//PermissionsFlag = true;
CCTVPath = "youtube.com";
}
private bool _permissionsFlag = false;
private string _cctvPath;
public bool PermissionsFlag
{
get { return _permissionsFlag; }
set
{
_permissionsFlag = value;
OnPropertyChanged("PermissionsFlag");
}
}
public string CCTVPath
{
get { return _cctvPath; }
set
{
_cctvPath = value;
OnPropertyChanged("CCTVPath");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
window xaml:
窗口xaml:
<Window x:Class="WpfDemos.Views.Window3"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window3" Height="300" Width="300">
<StackPanel>
<CheckBox Name="chkPermissionsFlag"
Content="PermissionsFlag"
IsChecked="{Binding Path=PermissionsFlag, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Text="{Binding Path=CCTVPath, UpdateSourceTrigger=PropertyChanged}"/>
<Button x:Name="cctvFeedButton" Content="Live Feed"
Width="100" FontSize="16" HorizontalAlignment="Right" Margin="5">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=CCTVPath}" Value="">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=PermissionsFlag}" Value="False">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</StackPanel>
</Window>
回答by John Colvin
An alternative solution is to use a single DataTrigger with a MultiBinding. You could make it work by defining a 'special-case' IMultiValueConverter that assumes 2 items in the object array, and returns true if the first item is an empty string OR the second item is false. However, you probably won't ever use that converter anywhere else in your code. So if you are willing to do a little more work up front, you could define 3 simple/reusable converters.
另一种解决方案是将单个 DataTrigger 与 MultiBinding 结合使用。您可以通过定义一个“特殊情况” IMultiValueConverter 来使其工作,该 IMultiValueConverter 假设对象数组中有 2 个项目,如果第一项是空字符串或第二项为假,则返回 true。但是,您可能永远不会在代码的其他任何地方使用该转换器。因此,如果您愿意预先做更多的工作,您可以定义 3 个简单/可重用的转换器。
1) an [IMultiValueConverter] 'OrConverter,' which would look something like this:
1) 一个 [IMultiValueConverter] 'OrConverter',它看起来像这样:
public class BooleanOrConverter : IMultiValueConverter {
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) {
return values.OfType<bool>().Any(b => b);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) {
throw new NotImplementedException();
}
}
2) An [IValueConverter] 'IsNullOrEmpty' string converter:
2) [IValueConverter] 'IsNullOrEmpty' 字符串转换器:
public class StringIsNullOrEmptyConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
return string.IsNullOrEmpty(value as string);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
throw new NotImplementedException();
}
}
3) And an [IValueConverter] 'NotConverter:'
3) 和 [IValueConverter] 'NotConverter:'
public class BooleanNotConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
return !(bool)value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
throw new NotImplementedException();
}
}
Then, in your xaml, the DataTrigger would be defined like this:
然后,在您的 xaml 中,DataTrigger 将被定义为:
<Button x:Name="cctvFeedButton" Content="Live Feed"
Width="100" FontSize="16" HorizontalAlignment="Right" Margin="5">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource OrConverter}">
<Binding Path="PermissionFlag" Converter="{StaticResource NotConverter}"/>
<Binding Path="CCTVPath" Converter="{StaticResource IsNullOrEmptyConverter}"/>
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
I prefer this solution over the use of 2 separate DataTriggers for readability; it better expresses the behavior you are defining - it is 'or' logic: a singular set of 2 conditions that should hide the button.
我更喜欢这个解决方案而不是使用 2 个单独的 DataTriggers 来提高可读性;它更好地表达了您正在定义的行为 - 它是“或”逻辑:应该隐藏按钮的 2 个条件的单一集合。

