具有特定属性的通用样式
General style with specific properties
我想要一个动态的 ToolTip
样式,它根据不同字符串属性的文本更改前景色(在这个代码示例中,字符串是 PosError
,但也可以是任何 属性 名称,如果值为“Error”,则触发 DataTrigger
。
至于现在,我必须对每个 TextBox
都这样做:更改 DataTrigger
的 属性 绑定和 [=11= 的文本](在这个例子中,字符串 属性 是 PosExtreme
):
<TextBox
Width="150"
FontSize="25"
MaxWidth="150"
Name="posTab"
TextAlignment="Center"
Text="{Binding PosTabStrength, UpdateSourceTrigger=PropertyChanged}">
<TextBox.ToolTip>
<ToolTip>
<ToolTip.Style>
<Style TargetType="{x:Type ToolTip}">
<Style.Triggers>
<DataTrigger Binding="{Binding PosError}" Value="Error">
<DataTrigger.Setters>
<Setter Property="Foreground">
<Setter.Value>
<LinearGradientBrush StartPoint="0 0" EndPoint="0 1">
<GradientStop Color="#F08080" Offset="0"/>
<GradientStop Color="#F04080" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</DataTrigger.Setters>
</DataTrigger>
</Style.Triggers>
<Setter Property="FontSize" Value="16"/>
<Setter Property="HasDropShadow" Value="True" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="Foreground">
<Setter.Value>
<LinearGradientBrush StartPoint="0 0" EndPoint="0 1">
<GradientStop Color="#10F080" Offset="0"/>
<GradientStop Color="#10B080" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Border
CornerRadius="3"
BorderThickness="1"
Background="#CF001233"
SnapsToDevicePixels="True"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush StartPoint="0 0" EndPoint="0 1">
<GradientStop Color="#A0A0F0" Offset="0"/>
<GradientStop Color="#8080F0" Offset="1"/>
<LinearGradientBrush.RelativeTransform>
<RotateTransform CenterX="0.5" CenterY="0.5"/>
</LinearGradientBrush.RelativeTransform>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Style.Triggers>
<EventTrigger RoutedEvent="Border.Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation
From="359"
To="0"
Duration="00:00:2"
Storyboard.TargetProperty="(Border.BorderBrush).(Brush.RelativeTransform).(RotateTransform.Angle)"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<ContentPresenter Margin="5" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ToolTip.Style>
<TextBlock Text="{Binding PosExtreme}"/>
</ToolTip>
</TextBox.ToolTip>
</TextBox>
我想将 ToolTip
样式作为 ResourceDictionary
文件,而不必复制和粘贴代码并为每个 TextBox
修改代码,使其正确 ToolTip
样式和 ToolTip
文本。
这可能吗?
重用样式的主要障碍是绑定到具体属性和 hard-coded Error
字符串。您需要从样式和控件模板外部传递它们。
您对 DataTrigger
的比较可以封装在一个值转换器中,该转换器 returns 一个布尔值,用于比较任何边界 属性 (PosError
) 与固定作为参数传递的值 (Error
)。
public class ErrorComparisonToBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value != null && parameter != null && value.Equals(parameter);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new InvalidOperationException();
}
}
在DataTrigger
中,我们不再绑定一个具体的属性,而是ToolTip
的Tag
,这是一个通用的属性 ].
Gets or sets an arbitrary object value that can be used to store custom information about this element.
我们假设比较已经为我们完成并且 Tag
只包含结果 true
或 false
。这简化了 DataTrigger
并且对 PosError
的依赖性消失了。
接下来就可以去掉ToolTip
里面的TextBlock
了。 ToolTip
is a ContentControl
并公开一个 Content
属性。此内容使用 ControlTemplate
内的 ContentPresenter
自动显示。对 PosExtreme
的依赖也消失了。
将样式移出范围内的资源字典并创建一个转换器实例。
<local:ErrorComparisonToBoolConverter x:Key="ErrorComparisonToBoolConverter"/>
<Style x:Key="MyToolTipStyle" TargetType="{x:Type ToolTip}">
<Style.Triggers>
<DataTrigger Binding="{Binding Tag, RelativeSource={RelativeSource Self}}" Value="True">
<DataTrigger.Setters>
<Setter Property="Foreground">
<Setter.Value>
<LinearGradientBrush StartPoint="0 0" EndPoint="0 1">
<GradientStop Color="#F08080" Offset="0"/>
<GradientStop Color="#F04080" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</DataTrigger.Setters>
</DataTrigger>
</Style.Triggers>
<Setter Property="FontSize" Value="16"/>
<Setter Property="HasDropShadow" Value="True" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="Foreground">
<Setter.Value>
<LinearGradientBrush StartPoint="0 0" EndPoint="0 1">
<GradientStop Color="#10F080" Offset="0"/>
<GradientStop Color="#10B080" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Border
CornerRadius="3"
BorderThickness="1"
Background="#CF001233"
SnapsToDevicePixels="True"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush StartPoint="0 0" EndPoint="0 1">
<GradientStop Color="#A0A0F0" Offset="0"/>
<GradientStop Color="#8080F0" Offset="1"/>
<LinearGradientBrush.RelativeTransform>
<RotateTransform CenterX="0.5" CenterY="0.5"/>
</LinearGradientBrush.RelativeTransform>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Style.Triggers>
<EventTrigger RoutedEvent="Border.Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation
From="359"
To="0"
Duration="00:00:2"
Storyboard.TargetProperty="(Border.BorderBrush).(Brush.RelativeTransform).(RotateTransform.Angle)"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<ContentPresenter Margin="5" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
您现在可以重用该样式并将 PosExtreme
或任何其他 属性 绑定到 ToolTip
的 Content
并将错误 [=73=] 绑定到 Tag
。 Tag
绑定使用值转换器将绑定值与作为 CommandParameter
.
传递的预期错误代码进行比较
<TextBox.ToolTip>
<ToolTip Style="{StaticResource MyToolTipStyle}"
Content="{Binding PosExtreme}"
Tag="{Binding PosError, ConverterParameter=Error, Converter={StaticResource ErrorComparisonToBoolConverter}}">
</ToolTip>
</TextBox.ToolTip>
备注
- 该解决方案使用
Tag
属性 传播错误 属性。在您的示例中,它可以工作,但是如果您需要在样式或控件模板中绑定更多属性,则必须为每个可以绑定的属性创建附加属性,而不是 Tag
。对于单个属性,Tag
很方便。
- 您还可以创建一个自定义
ToolTip
控件,它公开样式和控件模板中使用的属性的依赖属性而不是附加属性,并在其中进行比较。
- 根据数据项的实现方式,如果有意义,您可以通过公开布尔值 属性 完全消除转换器。
我想要一个动态的 ToolTip
样式,它根据不同字符串属性的文本更改前景色(在这个代码示例中,字符串是 PosError
,但也可以是任何 属性 名称,如果值为“Error”,则触发 DataTrigger
。
至于现在,我必须对每个 TextBox
都这样做:更改 DataTrigger
的 属性 绑定和 [=11= 的文本](在这个例子中,字符串 属性 是 PosExtreme
):
<TextBox
Width="150"
FontSize="25"
MaxWidth="150"
Name="posTab"
TextAlignment="Center"
Text="{Binding PosTabStrength, UpdateSourceTrigger=PropertyChanged}">
<TextBox.ToolTip>
<ToolTip>
<ToolTip.Style>
<Style TargetType="{x:Type ToolTip}">
<Style.Triggers>
<DataTrigger Binding="{Binding PosError}" Value="Error">
<DataTrigger.Setters>
<Setter Property="Foreground">
<Setter.Value>
<LinearGradientBrush StartPoint="0 0" EndPoint="0 1">
<GradientStop Color="#F08080" Offset="0"/>
<GradientStop Color="#F04080" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</DataTrigger.Setters>
</DataTrigger>
</Style.Triggers>
<Setter Property="FontSize" Value="16"/>
<Setter Property="HasDropShadow" Value="True" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="Foreground">
<Setter.Value>
<LinearGradientBrush StartPoint="0 0" EndPoint="0 1">
<GradientStop Color="#10F080" Offset="0"/>
<GradientStop Color="#10B080" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Border
CornerRadius="3"
BorderThickness="1"
Background="#CF001233"
SnapsToDevicePixels="True"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush StartPoint="0 0" EndPoint="0 1">
<GradientStop Color="#A0A0F0" Offset="0"/>
<GradientStop Color="#8080F0" Offset="1"/>
<LinearGradientBrush.RelativeTransform>
<RotateTransform CenterX="0.5" CenterY="0.5"/>
</LinearGradientBrush.RelativeTransform>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Style.Triggers>
<EventTrigger RoutedEvent="Border.Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation
From="359"
To="0"
Duration="00:00:2"
Storyboard.TargetProperty="(Border.BorderBrush).(Brush.RelativeTransform).(RotateTransform.Angle)"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<ContentPresenter Margin="5" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ToolTip.Style>
<TextBlock Text="{Binding PosExtreme}"/>
</ToolTip>
</TextBox.ToolTip>
</TextBox>
我想将 ToolTip
样式作为 ResourceDictionary
文件,而不必复制和粘贴代码并为每个 TextBox
修改代码,使其正确 ToolTip
样式和 ToolTip
文本。
这可能吗?
重用样式的主要障碍是绑定到具体属性和 hard-coded Error
字符串。您需要从样式和控件模板外部传递它们。
您对 DataTrigger
的比较可以封装在一个值转换器中,该转换器 returns 一个布尔值,用于比较任何边界 属性 (PosError
) 与固定作为参数传递的值 (Error
)。
public class ErrorComparisonToBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value != null && parameter != null && value.Equals(parameter);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new InvalidOperationException();
}
}
在DataTrigger
中,我们不再绑定一个具体的属性,而是ToolTip
的Tag
,这是一个通用的属性 ].
Gets or sets an arbitrary object value that can be used to store custom information about this element.
我们假设比较已经为我们完成并且 Tag
只包含结果 true
或 false
。这简化了 DataTrigger
并且对 PosError
的依赖性消失了。
接下来就可以去掉ToolTip
里面的TextBlock
了。 ToolTip
is a ContentControl
并公开一个 Content
属性。此内容使用 ControlTemplate
内的 ContentPresenter
自动显示。对 PosExtreme
的依赖也消失了。
将样式移出范围内的资源字典并创建一个转换器实例。
<local:ErrorComparisonToBoolConverter x:Key="ErrorComparisonToBoolConverter"/>
<Style x:Key="MyToolTipStyle" TargetType="{x:Type ToolTip}">
<Style.Triggers>
<DataTrigger Binding="{Binding Tag, RelativeSource={RelativeSource Self}}" Value="True">
<DataTrigger.Setters>
<Setter Property="Foreground">
<Setter.Value>
<LinearGradientBrush StartPoint="0 0" EndPoint="0 1">
<GradientStop Color="#F08080" Offset="0"/>
<GradientStop Color="#F04080" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</DataTrigger.Setters>
</DataTrigger>
</Style.Triggers>
<Setter Property="FontSize" Value="16"/>
<Setter Property="HasDropShadow" Value="True" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="Foreground">
<Setter.Value>
<LinearGradientBrush StartPoint="0 0" EndPoint="0 1">
<GradientStop Color="#10F080" Offset="0"/>
<GradientStop Color="#10B080" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Border
CornerRadius="3"
BorderThickness="1"
Background="#CF001233"
SnapsToDevicePixels="True"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush StartPoint="0 0" EndPoint="0 1">
<GradientStop Color="#A0A0F0" Offset="0"/>
<GradientStop Color="#8080F0" Offset="1"/>
<LinearGradientBrush.RelativeTransform>
<RotateTransform CenterX="0.5" CenterY="0.5"/>
</LinearGradientBrush.RelativeTransform>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Style.Triggers>
<EventTrigger RoutedEvent="Border.Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation
From="359"
To="0"
Duration="00:00:2"
Storyboard.TargetProperty="(Border.BorderBrush).(Brush.RelativeTransform).(RotateTransform.Angle)"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<ContentPresenter Margin="5" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
您现在可以重用该样式并将 PosExtreme
或任何其他 属性 绑定到 ToolTip
的 Content
并将错误 [=73=] 绑定到 Tag
。 Tag
绑定使用值转换器将绑定值与作为 CommandParameter
.
<TextBox.ToolTip>
<ToolTip Style="{StaticResource MyToolTipStyle}"
Content="{Binding PosExtreme}"
Tag="{Binding PosError, ConverterParameter=Error, Converter={StaticResource ErrorComparisonToBoolConverter}}">
</ToolTip>
</TextBox.ToolTip>
备注
- 该解决方案使用
Tag
属性 传播错误 属性。在您的示例中,它可以工作,但是如果您需要在样式或控件模板中绑定更多属性,则必须为每个可以绑定的属性创建附加属性,而不是Tag
。对于单个属性,Tag
很方便。 - 您还可以创建一个自定义
ToolTip
控件,它公开样式和控件模板中使用的属性的依赖属性而不是附加属性,并在其中进行比较。 - 根据数据项的实现方式,如果有意义,您可以通过公开布尔值 属性 完全消除转换器。