为了让我们WPF控件样式能够重复利用和解耦,我们可以通过附加属性来给我们的样式添加扩展。今天就带大家看看如果使用扩展属性来定制样式!
假设一种应用场景:我们需要做一个状态按钮控件,但鼠标按下去的时候,呈现一种图片,弹起来的时候呈现一种图片。所以我们给他加两个附加属性:PressedIcon,ReleasedIcon.
先定义两个附加属性:
public class UIHelper
{
/// <summary>
/// 默认图标附加属性
/// </summary>
public readonly static DependencyProperty PressedIconProperty = DependencyProperty.RegisterAttached("PressedIcon", typeof(ImageSource), typeof(UIHelper));
/// <summary>
///
/// </summary>
/// <param name="frameworkElement"></param>
/// <returns></returns>
public static ImageSource GetPressedIcon(FrameworkElement frameworkElement)
{
return (ImageSource)frameworkElement.GetValue(PressedIconProperty);
}
/// <summary>
///
/// </summary>
/// <param name="frameworkElement"></param>
/// <param name="value"></param>
public static void SetPressedIcon(FrameworkElement frameworkElement, ImageSource value)
{
frameworkElement.SetValue(PressedIconProperty, value);
}
public readonly static DependencyProperty ReleasedIconProperty = DependencyProperty.RegisterAttached("ReleasedIcon", typeof(ImageSource), typeof(UIHelper));
/// <summary>
///
/// </summary>
/// <param name="frameworkElement"></param>
/// <returns></returns>
public static ImageSource GetReleasedIcon(FrameworkElement frameworkElement)
{
return (ImageSource)frameworkElement.GetValue(ReleasedIconProperty);
}
/// <summary>
///
/// </summary>
/// <param name="frameworkElement"></param>
/// <param name="value"></param>
public static void SetReleasedIcon(FrameworkElement frameworkElement, ImageSource value)
{
frameworkElement.SetValue(ReleasedIconProperty, value);
}
}
附加属性定义好后,我们只需要在Xaml
代码中引用他们,并给予赋值。
RadioButton
示例样式:
<Style x:Key="RadioButtonStyle" TargetType="{x:Type RadioButton}">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Foreground" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<Grid x:Name="markGrid" Background="Transparent">
<Ellipse x:Name="optionMark" Fill="Transparent" Width="{Binding ActualHeight, RelativeSource={RelativeSource Mode=Self}}"/>
<Image x:Name="img" Margin="{Binding ActualHeight,RelativeSource={RelativeSource Mode=TemplatedParent},Converter={StaticResource EllipseMarginConverter}}" Source="{Binding Path=(helper:UIHelper.ReleasedIcon),RelativeSource={ RelativeSource Mode=TemplatedParent}}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Fill" TargetName="optionMark" Value="{StaticResource RadioButton.MouseOver.Glyph}"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Fill" TargetName="optionMark" Value="{StaticResource RadioButton.Pressed.Glyph}"/>
</Trigger>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Source" TargetName="img" Value="{Binding Path=(helper:UIHelper.PressedIcon),RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
<Setter Property="Fill" Value="{StaticResource RadioButton.MouseOver.Glyph}" TargetName="optionMark"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
在我们控件中使用他们:
<UserControl x:Class="Hilk.InkMarker.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:helper="clr-namespace:test.XamlUI"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<!--此处省略静态资源字典的引入,包含:PressedIcon和ReleasedIcon-->
<Grid>
<RadioButton Style="{StaticResource RadioButtonStyle}" helper:UIHelper.PressedIcon="{StaticResource PressedIcon}" helper:UIHelper.ReleasedIcon="{StaticResource ReleasedIcon}"/>
</Grid>
</UserControl>
这样就可以通过附加属性,给我们的控件定制化样式了。
本文会经常更新,请阅读原文: https://huchengv5.gitee.io//post/WPF%E9%80%9A%E8%BF%87%E9%99%84%E5%8A%A0%E5%B1%9E%E6%80%A7%E7%BB%99%E6%8E%A7%E4%BB%B6%E4%BF%AE%E6%94%B9%E6%A0%B7%E5%BC%8F.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名胡承(包含链接: https://huchengv5.gitee.io/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 。