在创建用户控件时,我们难免会创建依赖项属性,这样有利于用户控件的灵活性,例如:我写了一个控件MenuButton,这个MenuButton就是为Button写了一个模板,Image用来显示图片,ContentPresenter用来显示文本。我们肯定不是在用户控件中将图片和文字预先设置好,而是通过用户控件属性来设置,在这里说一些额外的话,建议用依赖项属性,因为依赖项属性支持例如:设计器集成、Binding、动画、样式、动态资源等,而属性则不支持的。看以下MenuButton.xaml代码片段:
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:Jeriffe.SL.App.UserControlBinding"
mc:Ignorable ="d" >
< UserControl.Resources >
< Style x:Key ="ButtonStyle" TargetType ="Button" >
< Setter Property ="Template" >
< Setter.Value >
< ControlTemplate TargetType ="Button" >
< Grid >
< Rectangle x:Name ="rectangle" Fill ="#FFCCCCD6"
Height ="41"
RadiusX ="8"
RadiusY ="8"
Stroke ="#FF5A5353" />
< StackPanel Orientation ="Horizontal" >
< Image
HorizontalAlignment ="Center"
Height ="32"
Margin ="10,0,0,0"
Source =" {Binding Source} "
Stretch ="Fill" Width ="32"
VerticalAlignment ="Center" />
< ContentPresenter
VerticalAlignment ="Center"
Width ="22"
Margin ="10,0"
Content =" {Binding Text} " />
</ StackPanel >
</ Grid >
</ ControlTemplate >
</ Setter.Value >
</ Setter >
</ Style >
</ UserControl.Resources >
< Grid x:Name ="LayoutRoot" >
< Button Style =" {StaticResource ButtonStyle} " />
</ Grid >
</ UserControl >
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace Jeriffe.SL.App.UserControlBinding
{
public partial class MenuButton : UserControl
{
public MenuButton()
{
InitializeComponent();
// this.DataContext = this;
}
public static readonly DependencyProperty SourceProperty =
DependencyProperty.Register(
" Source ",
typeof(ImageSource),
typeof(MenuButton),
new PropertyMetadata( default(ImageSource)));
public ImageSource Source
{
get { return (ImageSource)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
" Text ",
typeof( string),
typeof(MenuButton),
new PropertyMetadata( default( string)));
public string Text
{
get { return ( string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
}
}
那么我们如何将自定义的依赖项属性Source绑定到Image,Text绑定到Content上?且看如下3种方法:
第一种方法:在XAML中为UserControl指定x:Name值,Binding通过ElementName进行绑定。
好吧,如上所说,我们为UserControl指定x:Name值,如下
MenuButton.xaml文件:
xmlns:local="clr-namespace:Jeriffe.SL.App.UserControlBinding"
x:Name="UserControl_MenuButton">
修改Image和ContentPresenter的Binding,代码如下(改动的代码是蓝色的):
MenuButton.xaml文件:
Height ="32"
Margin ="10,0,0,0"
Source ="{Binding ElementName=UserControl_MenuButton,Path=Source}"
Stretch ="Fill"
Width ="32"
VerticalAlignment ="Center" />
< ContentPresenter
VerticalAlignment ="Center"
Width ="22"
Margin ="10,0"
Content ="{Binding ElementName=UserControl_MenuButton, Path=Text}" />
如上,就可以将依赖项属性Source和Text绑定到Image和ContentPresenter上。不过这种方式有一个致命的缺点就是:当这个自定义控件在同一个页面有1个以上时,偶尔会抛出已经定义UserControl_MenuButton异常。所以这种方式不可取。
第二种方法:在MenuButton.xaml.cs中的MenuButton实例构造器中将this.DataContext=this;这样,其实和上一种实现的方式差不多,不过这样不用为UserControl指定x:Name值,也不会出现上面所提到的神马已经定义UserControl_MenuButton异常。看下面代码:
MenuButton.xaml.cs文件
{
InitializeComponent();
this.DataContext = this;
}
这种方法也不错,不过有的家伙比喜欢(不喜欢在后台写代码,能在XAML中实现的绝不在.cs文件中实现)。
第三种方法:在XAML中设置UserControl的DataContext绑定自身。请看一下代码:
xmlns:local ="clr-namespace:Jeriffe.SL.App.UserControlBinding"
mc:Ignorable ="d"
DataContext ="{Binding RelativeSource={RelativeSource Self}}">
好吧,有的童鞋可能不懂这种Binding的语法的意思,上链接:Binding.RelativeSource 属性。
原文摘自: