[英]WPF Binding: Fallback to value defined in Style
WPF颜色绑定如何恢复为默认值?
这是我正在尝试做的事情:
<TextBox Text="Some Binding"/>
将产生一个文本框,该文本框具有在其他位置定义的某些背景色。
<Textbox Text="Some Binding"
Background = "{Binding Path=Status,
TargetNullValue='Same color as the Textbox above, please',
Converter=***}"/>
该文本框应该根据状态更改其颜色(可以正常工作),但是对于某些值,我希望背景恢复为完全没有绑定时将使用的颜色。
附加信息:我在资源字典中使用这些文本框。
<ResourceDictionary>
<Style TargetType=**MyTreeControl**>
<Style.Resources>
<HierarchicalDataTemplate ***>
<Textboxes from above/>
非常感谢你!
编辑:最后,我使用了@Mike的解决方案,我觉得它很优雅。
但是我很感兴趣为什么这可行,而昨天却没有
<DataTrigger Binding="{Binding Path=Status }" Value="1">
<Setter Property="Background" Value="Lime"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Status }" Value="2">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
因此,再次尝试,今天它也正常工作。 对我来说似乎就像WPF一样神奇。
但是对于某些值,我希望背景恢复为颜色
将此逻辑放在转换器中(因为您已经在使用一个)。
public class MyStatusToBackgroundConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Status status = (Status)value;
// maybe use a switch statement depending on number of cases?
if (status == Status.SomeValue || status == Status.SomeOtherValue)
return Brushes.Brushes.Transparent;
else
{
// ...
}
}
}
基本上,您不能明确回退。 最好的选择是仅在您确实要为状态设置颜色时才有条件地设置颜色。 这可以通过样式触发器来完成。 这是一个基于文本框文本不为null或为空而执行类似操作的示例:
<Window.Resources>
<!-- emulate some default style -->
<Style TargetType="{x:Type TextBox}">
<Setter Property="Background" Value="Yellow"/>
</Style>
<local:TestColorConverter x:Key="colorConverter"/>
</Window.Resources>
<!-- ... -->
<TextBox Text="a Status">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Style.Triggers>
<DataTrigger Binding="{Binding Text,RelativeSource={RelativeSource Self},Converter={StaticResource colorConverter},ConverterParameter='Check'}" Value="True">
<Setter Property="Background" Value="{Binding Text,RelativeSource={RelativeSource Self},Converter={StaticResource colorConverter}}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
转换器具有两种模式:(1)返回True / False以指示状态是否具有自定义颜色(2)返回具有自定义状态颜色的Brush
public class TestColorConverter : IValueConverter
{
// the question doesn't explain the status type, so I use string.
// probably replace string with your actual status type
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (string.Equals("Check", parameter as string))
{
return HasColor(value as string);
}
return GetColor(value as string);
}
private bool HasColor(string status)
{
return GetColor(status) != null;
}
private Brush GetColor(string status)
{
if (string.IsNullOrWhiteSpace(status))
{
return null;
}
if (status.StartsWith("a"))
{
return Brushes.Red;
}
return Brushes.DarkGoldenrod;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
您尝试做的事情很棘手,因为您在Background
设置的任何Binding
都将优先于本应应用的值。
您需要的是一种有条件地设置Binding
。 @ grek40的解决方案是在正确的轨道上,但是条件逻辑需要评估建议绑定的输出 ,而不是该绑定的输入 。
首先,您将需要一个与建议的@ grek40类似的转换器,但有可能深入到另一个转换器。 请注意,此转换器依赖于状态-画笔转换器,当不设置颜色时返回null 。
public class IsNotNullConverter : IValueConverter
{
public IValueConverter InnerConverter { get; set; }
public object Convert(
object value,
Type targetType,
object parameter,
CultureInfo culture)
{
if (InnerConverter != null)
value = InnerConverter.Convert(value, targetType, parameter, culture);
return value != null &&
value != DependencyProperty.UnsetValue;
}
public object ConvertBack(
object value,
Type targetType,
object parameter,
CultureInfo culture)
{
return Binding.DoNothing;
}
}
在声明您的文本框的模板内,您将需要一个触发器,该触发器有条件地应用Background
绑定:
<DataTemplate>
<DataTemplate.Resources>
<l:StatusToBrushConverter x:Key="StatusConverter" />
<l:IsNotNullConverter x:Key="ShouldApplyStatusConverter"
InnerConverter="{StaticResource StatusConverter}" />
</DataTemplate.Resources>
<TextBox x:Name="_textBox" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=Status,
Converter={StaticResource ShouldApplyStatusConverter}}"
Value="True">
<Setter TargetName="_textBox"
Property="Background"
Value="{Binding Path=Status,
Converter={StaticResource StatusConverter}}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
这将不起作用,因为Background
的第二个设置器将始终覆盖第一个设置器:
<!-- Set the background based on the level into the tree. -->
<Setter Property="Background" Value="{Binding DataItem.Level, Converter={StaticResource IntegerToBrushConverter}}"/>
<!-- Row is red if no live updates received for N seconds -->
<Setter Property="Background" Value="{Binding DataItem.IsStale, Converter={StaticResource IsStaleToBackgroundConverter}}"/>
要解决此问题,请包装DataTrigger
,因此,如果值为False
则甚至不会评估Background
的第二个设置器:
<Setter Property="Background" Value="{Binding DataItem.Level, Converter={StaticResource IntegerToBrushConverter}}"/>
<!-- Row is red if no live updates received for N seconds -->
<Style.Triggers>
<DataTrigger Binding="{Binding DataItem.IsStale}" Value="True">
<Setter Property="Background" Value="{Binding DataItem.IsStale, Converter={StaticResource IsStaleToBackgroundConverter}}"/>
</DataTrigger>
</Style.Triggers>
这意味着将应用Background
的第一个设置器,如果IsStale
值为false, IsStale
忽略第二个设置器。
转换器:
public class BooleanToBrushConverter : ValueConverterBase
{
public Brush TrueBrush { get; set; }
public Brush FalseBrush { get; set; }
public Brush DefaultBrush { get; set; }
public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
try
{
if (value==null)
{
return null;
}
var booleanValue = (bool)value;
return booleanValue ? this.TrueBrush : this.FalseBrush;
}
catch (InvalidCastException)
{
return this.DefaultBrush;
}
}
}
这介于.Resources
标签之间:
<colorBrushes:BooleanToBrushConverter x:Key="IsStaleToBackgroundConverter"
TrueBrush="{StaticResource RedStaleBrush}"
FalseBrush="{StaticResource TransparentBrush}"
DefaultBrush="{StaticResource TransparentBrush}" />
您还必须定义颜色,或将其替换为常量,例如DefaultBrush="Green"
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.