非常重要
依赖属性和附加属性,两者是有关系的,也是有些区别的,很多时候,可能会把两者混淆了。
依赖属性(Dependency property)
就是一种自己没有值,并能通过使用Binding从数据源获取值,也就是依赖别人身上的属性,拥有依赖属性的对象,称为依赖对象。
1.首先看一下依赖属性怎么建立的,输入propdp,点击tab按钮2次,就会自动出现
2.建立一个默认的依赖属性
补充:如果建立一个类报错的话
继承依赖对象就没有报错了,上面继承的Windows其实也是继承了依赖对象,所以不会报错
其实点击任意一个控件,看里面的属性,都含有依赖属性
3. 使用依赖属性给Button增加鼠标划过显示颜色,建立一个类,继承Button
4.使用快捷键propdp建立完成,代码如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace WpfApp2
{
public class ButtonEx : Button
{
static ButtonEx()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ButtonEx), new FrameworkPropertyMetadata(typeof(ButtonEx)));//使ButtonEx去读取ButtonEx类型的样式,而不是去读取Button的样式
}
public int MyButtonEx
{
get { return (int)GetValue(ButtonExProperty); }
set { SetValue(ButtonExProperty, value); }
}
// Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ButtonExProperty =
DependencyProperty.Register("MyButtonEx", typeof(int), typeof(ButtonEx), new PropertyMetadata(0));
//依赖属性名称,依赖属性数据类型,所属哪个类中,属性的元数据
}
}
5.建立ButtonEx的样式,建立资源字典Dictionary1.xaml
6.增加样式
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp2"
>
<Style TargetType="{x:Type local:ButtonEx}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<DockPanel Name="dpCon" Width="{Binding Width, RelativeSource={x:Static RelativeSource.TemplatedParent}}"
Height="{Binding Height, RelativeSource={x:Static RelativeSource.TemplatedParent}}"
Background="{Binding Background, RelativeSource={x:Static RelativeSource.TemplatedParent}}"
ToolTip="{Binding ToolTip, RelativeSource={x:Static RelativeSource.TemplatedParent}}"
>
<DockPanel DockPanel.Dock="Top" Name="dpBtn">
<DockPanel.Background>
<ImageBrush ImageSource="{Binding ForeImage, RelativeSource={x:Static RelativeSource.TemplatedParent}}" Stretch="{Binding Stretch,RelativeSource={x:Static RelativeSource.TemplatedParent}}"/>
</DockPanel.Background>
<TextBlock FontSize="15" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="#f9fcff" Text="{Binding Content, RelativeSource={x:Static RelativeSource.TemplatedParent}}"></TextBlock>
</DockPanel>
</DockPanel>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding IsMouseOver,RelativeSource={x:Static RelativeSource.Self}}" Value="True">
<Setter Property="Background" TargetName="dpBtn">
<Setter.Value>
<ImageBrush ImageSource="{Binding BackImage, RelativeSource={x:Static RelativeSource.TemplatedParent}}" Stretch="{Binding Stretch,RelativeSource={x:Static RelativeSource.TemplatedParent}}"/>
</Setter.Value>
</Setter>
<Setter Property="Background" TargetName="dpCon" Value="{Binding MouseOverBackColor, RelativeSource={x:Static RelativeSource.TemplatedParent}}"></Setter>
</DataTrigger>
<Trigger Property="IsEnabled" Value="true"/>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="Gray"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
7.前台界面
可见,经过依赖属性之后,ButtonEx按钮就带了MouseOverBackColor属性,可以对其进行设置颜色。 依赖修改的比附加更多。依赖是整体都修改了,而附加是用哪个再附加哪个。
附加属性(DependencyProperty)
顾名思义,就是附加上面的属性,自身是没有的,别人附加上面的,就变成了自己的属性,就可以使用点. 点击 出来。比如说,wpf中PasswordBox控件是不能进行绑定数据的,但是你把它绑定一个密码,那么就是附加属性了。附加属性,也属于一种依赖属性。
1.附加属性建立,输入propa,点击tab按钮2次
2.修改对应的参数
public static string GetPassword(DependencyObject obj)
{
return (string)obj.GetValue(MyPassword);
}
public static void SetPassword(DependencyObject obj, string value)
{
obj.SetValue(MyPassword, value);
}
// Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyPassword =
DependencyProperty.RegisterAttached("Password", typeof(string), typeof(MainWindow), new PropertyMetadata(null));
3.前端进行调用
<Window x:Class="WpfApp2.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:WpfApp2"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<PasswordBox local:MainWindow.Password="{Binding PW}" HorizontalAlignment="Left" Margin="416,183,0,0" VerticalAlignment="Top" Width="120"/>
</Grid>
</Window>
4.写调用方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApp2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
PW = "123456";
this.DataContext = this;
}
public static string GetPassword(DependencyObject obj)
{
return (string)obj.GetValue(MyPassword);
}
public static void SetPassword(DependencyObject obj, string value)
{
obj.SetValue(MyPassword, value);
}
// Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyPassword =
DependencyProperty.RegisterAttached("Password", typeof(string), typeof(MainWindow), new PropertyMetadata((s,e)=>
{
var pw = s as PasswordBox;
pw.Password = e.NewValue.ToString();
})); //这里和xaml中建立关系
public string PW { get; set; }
}
}