我正在尝试使用触发器设置矩形(WPF)的颜色,具体取决于布尔值DependencyProperty,我将其绑定到矩形的Tag属性。
我有以下代码:
public partial class MainWindow : Window
{
public Boolean isAutoStart
{
get { return (Boolean)GetValue(isAutoStartProperty); }
set { SetValue(isAutoStartProperty, value); }
}
public static readonly DependencyProperty isAutoStartProperty =
DependencyProperty.Register("isAutoStart", typeof(Boolean),
typeof(MainWindow), new PropertyMetadata(true));
private void Window_Loaded(object sender, RoutedEventArgs e)
{
isAutoStart = false;
}
}
并在XAML中:
<Window.Resources>
<Style x:Key="TriggerDark" TargetType="Rectangle">
<Setter Property="Fill" Value="Green" />
<Style.Triggers>
<Trigger Property="Tag" Value="False">
<Setter Property="Fill" Value="Red" />
</Trigger>
<Trigger Property="Tag" Value="True">
<Setter Property="Fill" Value="Green" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Rectangle Style="{StaticResource ResourceKey=TriggerDark}" Tag="{Binding Path=isAutoStart, UpdateSourceTrigger=PropertyChanged}">
如果我将“True”或“False”硬编码到矩形的tag属性中,则触发器可以正常工作。 如果我在运行时将tag属性的值打印到控制台,则绑定有效,但触发器不会触发。
任何想法我做错了什么?
谢谢!
答案 0 :(得分:2)
你的触发器试图将布尔值true与字符串&#34; True&#34;进行比较。因为Tag是一个Object属性所以将存储布尔值,而Trigger的值是一个String。 PHP希望它,而不是WPF。 ;)
如果要保留Trigger而不是DataTrigger,可以创建一个静态类:
public static class BooleanHelper {
public static bool False {
get { return false; }
}
public static bool True {
get { return true; }
}
}
然后风格将写成:
<Style x:Key="TriggerDark" TargetType="Rectangle">
<Setter Property="Fill" Value="Green"/>
<Style.Triggers>
<Trigger Property="Tag" Value="{x:Static local:BooleanHelper.True}">
<Setter Property="Fill" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
感谢Michael Mairegger这个想法。
答案 1 :(得分:1)
您可以尝试使用DataTrigger:
(请注意,您也可以简化您的风格,删除触发器)
<Style x:Key="TriggerDark" TargetType="Rectangle">
<Setter Property="Fill" Value="Green" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=isAutoStart}" Value="False">
<Setter Property="Fill" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
将datacontext设置为窗口:
public MainWindow()
{
DataContext = this;
}
修改强>: 如果您愿意,可以使用IValueConverter:
public class BoolToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
if (targetType != typeof(bool))
throw new InvalidOperationException("The target must be a boolean");
return value.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}
并将绑定更改为:
<Window.Resources>
<local:BoolToStringConverter x:Key="BtSConv"/>
<Style x:Key="TriggerDark" TargetType="Rectangle">
<Setter Property="Fill" Value="Green" />
<Style.Triggers>
<Trigger Property="Tag" Value="False">
<Setter Property="Fill" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Rectangle Style="{StaticResource TriggerDark}" Tag="{Binding isAutoStart, Converter={StaticResource BtSConv}}" />
即使其他人也有很多美丽的解决方案。
答案 2 :(得分:1)
您需要设置绑定的DataContext
。现在,您的绑定指向Rectangle.DataContext.isAutoStart
,但Rectangle.DataContext
为空,因此您的绑定不会解析为任何内容。有关DataContext
的详细信息,请参阅this answer。
因为您提到here您不想使用DataTrigger
进行硬编码,您可能需要手动设置绑定的Source
以搜索可视树到第一个而是Window
对象,并绑定到该属性的isAutoStart
属性。
<Rectangle Tag="{Binding Path=isAutoStart, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" .. />
您还有this answer所指出的额外问题,您将布尔值与字符串进行比较,因此它总是评估为False。有很多方法可以解决这个问题,例如IValueConverter
,但我发现最简单的方法是导入系统命名空间并为布尔值true创建一个静态值,如图here所示:
<s:Boolean x:Key="TrueValue">True</s:Boolean>
...
<Trigger Property="Tag" Value="{StaticResource TrueValue}">
s
命名空间定义为
xmlns:s="clr-namespace:System;assembly=mscorlib"
答案 3 :(得分:1)
用户nkoniishvt已经给出了解释,触发器将Tag
属性值与字符串文字“True”和“False”进行比较,而不是bool
值。
此问题的替代解决方法可能不是使用Tag
属性,而是使用正确类型的附加属性,例如,如
public static class StyleHelper
{
public static readonly DependencyProperty StateProperty =
DependencyProperty.RegisterAttached(
"State", typeof(bool), typeof(StyleHelper));
public static bool GetState(DependencyObject obj)
{
return (bool)obj.GetValue(StateProperty);
}
public static void SetState(DependencyObject obj, bool value)
{
obj.SetValue(StateProperty, value);
}
}
您可以在XAML中使用它,如下所示:
<Window.Resources>
<Style TargetType="Rectangle">
<Setter Property="Fill" Value="Green" />
<Style.Triggers>
<Trigger Property="local:StyleHelper.State" Value="False">
<Setter Property="Fill" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Rectangle local:StyleHelper.State="{Binding isAutoStart}}" />