非常重要
依赖属性和附加属性,两者是有关系的,也是有些区别的,很多时候,可能会把两者混淆了。
依赖属性(Dependency property)
就是一种自己没有值,并能通过使用Binding从数据源获取值,也就是依赖别人身上的属性,拥有依赖属性的对象,称为依赖对象。
1.下面举例给按钮增加一个依赖属性,把图片和按钮封装在一起,当做一个控件来使用,创建一个项目
2.增加一个类ButtonEx,继承Button
创建ButtonEx类的时候,选择“自定义控件”即可,会自动产生模板。
可以使用快捷键创建,输入propdp,点击tab按钮2次,就会自动出现
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows;
using System.Windows.Controls;
namespace btnDemo
{
public class ButtonEx : Button
{
static ButtonEx()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ButtonEx), new FrameworkPropertyMetadata(typeof(ButtonEx)));//使ButtonEx去读取ButtonEx类型的样式,而不是去读取Button的样式
}
public ButtonType ButtonType //定义按钮的类型
{
get { return (ButtonType)GetValue(ButtonTypeProperty); }
set { SetValue(ButtonTypeProperty, value); }
}
public static readonly DependencyProperty ButtonTypeProperty =
DependencyProperty.Register("ButtonType", typeof(ButtonType), typeof(ButtonEx), new PropertyMetadata(ButtonType.Normal, OnButtonTypeChangedCallback));
//此方法是回调
private static void OnButtonTypeChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
//此处回调,可以修改按钮上面的默认值,初始化的时候,就走这里
var res = d as ButtonEx;
res.ButtonType = (ButtonType)e.NewValue;
//throw new NotImplementedException();
}
public ImageSource Icon //图片
{
get { return (ImageSource)GetValue(IconProperty); }
set { SetValue(IconProperty, value); }
}
public static readonly DependencyProperty IconProperty =
DependencyProperty.Register("Icon", typeof(ImageSource), typeof(ButtonEx), new PropertyMetadata(null));
//依赖属性名称,依赖属性数据类型,所属哪个类中,默认属性的元数据
//public CornerRadius CornerRadius
//{
// get { return (CornerRadius)GetValue(CornerRadiusProperty); }
// set { SetValue(CornerRadiusProperty, value); }
//}
//public static readonly DependencyProperty CornerRadiusProperty =
// DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(ButtonEx), new PropertyMetadata(new CornerRadius(0)));
public Brush MouseOverForeground
{
get { return (Brush)GetValue(MouseOverForegroundProperty); }
set { SetValue(MouseOverForegroundProperty, value); }
}
public static readonly DependencyProperty MouseOverForegroundProperty =
DependencyProperty.Register("MouseOverForeground", typeof(Brush), typeof(ButtonEx), new PropertyMetadata());
public Brush MouseOverBackground //鼠标滑动的时候,背景变色
{
get { return (Brush)GetValue(MouseOverBackgroundProperty); }
set { SetValue(MouseOverBackgroundProperty, value); }
}
public static readonly DependencyProperty MouseOverBackgroundProperty =
DependencyProperty.Register("MouseOverBackground", typeof(Brush), typeof(ButtonEx), new PropertyMetadata());
public Brush MousePressedForeground
{
get { return (Brush)GetValue(MousePressedForegroundProperty); }
set { SetValue(MousePressedForegroundProperty, value); }
}
public static readonly DependencyProperty MousePressedForegroundProperty =
DependencyProperty.Register("MousePressedForeground", typeof(Brush), typeof(ButtonEx), new PropertyMetadata());
public Brush MousePressedBackground
{
get { return (Brush)GetValue(MousePressedBackgroundProperty); }
set { SetValue(MousePressedBackgroundProperty, value); }
}
public static readonly DependencyProperty MousePressedBackgroundProperty =
DependencyProperty.Register("MousePressedBackground", typeof(Brush), typeof(ButtonEx), new PropertyMetadata());
}
/// <summary>
/// 按钮和图片组合的类型
/// </summary>
public enum ButtonType
{
Normal,
Icon,
Text,
IconText, //图片在左边
TextIcon //图片在右边
}
}
3.建立ButtonEx的样式,建立资源字典Dictionary1.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="clr-namespace:btnDemo"
>
<Style TargetType="{x:Type Controls:ButtonEx}">
<Style.Triggers>
<Trigger Property="ButtonType" Value="Normal">
<Setter Property="Background" Value="#43a9c7"/>
<Setter Property="MouseOverBackground" Value="#2f96b4"/>
<Setter Property="MousePressedBackground" Value="#2a89a4"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="MouseOverForeground" Value="White"/>
<Setter Property="MousePressedForeground" Value="White"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Controls:ButtonEx}">
<Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" SnapsToDevicePixels="True">
<TextBlock x:Name="txt" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="{Binding MouseOverBackground,RelativeSource={RelativeSource TemplatedParent}}"/>
<Setter TargetName="txt" Property="Foreground" Value="{Binding MouseOverForeground,RelativeSource={RelativeSource TemplatedParent}}"/>
<Setter TargetName="border" Property="BorderBrush" Value="{Binding MouseOverBorderbrush,RelativeSource={RelativeSource TemplatedParent}}"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="border" Property="Background" Value="{Binding MousePressedBackground,RelativeSource={RelativeSource TemplatedParent}}"/>
<Setter TargetName="txt" Property="Foreground" Value="{Binding MousePressedForeground,RelativeSource={RelativeSource TemplatedParent}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="ButtonType" Value="Icon">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Controls:ButtonEx}">
<Border Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
<Image x:Name="Img" VerticalAlignment="Center" HorizontalAlignment="Center" Source="{TemplateBinding Icon}" Stretch="None"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Opacity" Value="0.8"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Opacity" Value="0.9"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="ButtonType" Value="Text">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Foreground" Value="#002c99"/>
<Setter Property="MouseOverForeground" Value="#FF2c99"/>
<Setter Property="MousePressedForeground" Value="#002c99"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Controls:ButtonEx}">
<TextBlock x:Name="txt" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{Binding MouseOverForeground,RelativeSource={RelativeSource TemplatedParent}}" TargetName="txt"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Foreground" Value="{Binding MousePressedForeground,RelativeSource={RelativeSource TemplatedParent}}" TargetName="txt"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
<!--图片在左-->
<Trigger Property="ButtonType" Value="IconText">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Foreground" Value="#555"/>
<Setter Property="MouseOverForeground" Value="#555"/>
<Setter Property="MousePressedForeground" Value="#555"/>
<Setter Property="MouseOverBackground" Value="#555"/>
<Setter Property="MousePressedBackground" Value="#555"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Controls:ButtonEx}">
<Border Name="bor">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Image Source="{TemplateBinding Icon}" Stretch="None"/>
<TextBlock x:Name="Txt" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{Binding MouseOverForeground,RelativeSource={RelativeSource TemplatedParent}}" TargetName="Txt"/>
<Setter Property="Background" Value="{Binding MouseOverBackground ,RelativeSource={RelativeSource TemplatedParent}}" TargetName="bor"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Foreground" Value="{Binding MousePressedForeground,RelativeSource={RelativeSource TemplatedParent}}" TargetName="Txt"/>
<Setter Property="Background" Value="{Binding MousePressedBackground ,RelativeSource={RelativeSource TemplatedParent}}" TargetName="bor"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
<!--图片在右-->
<Trigger Property="ButtonType" Value="TextIcon">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Foreground" Value="#555"/>
<Setter Property="MouseOverForeground" Value="#555"/>
<Setter Property="MousePressedForeground" Value="#555"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Controls:ButtonEx}">
<Border>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock x:Name="Txt" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<Image Source="{TemplateBinding Icon}" Stretch="None"/>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{Binding MouseOverForeground,RelativeSource={RelativeSource TemplatedParent}}" TargetName="Txt"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Foreground" Value="{Binding MousePressedForeground,RelativeSource={RelativeSource TemplatedParent}}" TargetName="Txt"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
别忘记在App.xaml中引用
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/WpfApp4;component/Dictionary1.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
4.前台界面
<Window x:Class="btnDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:btnDemo"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
<Button Width="200" Height="50" Content="13212" Background="Red" />
<local:ButtonEx Width="200" Height="50" Content="图在左" Icon="/imgs/1.png" MouseOverForeground="Green" MouseOverBackground="Blue" MousePressedForeground="Red" MousePressedBackground="Yellow" Click="ButtonEx_Click" Background="Red" ButtonType="IconText"/>
<local:ButtonEx Width="200" Height="50" Content="图在右" Icon="/imgs/1.png" ButtonType="TextIcon" />
</StackPanel>
</Grid>
</Window>
5.效果
可见,经过依赖属性之后,ButtonEx按钮就带了Icon属性,等等其他属性,可以对其进行设置颜色。
在ButtonEx类中建立的属性,需要在xaml中去使用,2者需要结合起来使用,如果是封装控件那么2者都需要(在类和xaml中),如果是改变单独的控件,只需要在xaml中写样式就行了。
源码
https://download.csdn.net/download/u012563853/88623261
来源: