Silverlight 自定义控件中的自定义依赖项属性与控件绑定的几种方法
在创建用户控件时,我们难免会创建依赖项属性,这样有利于用户控件的灵活性,例如:我写了一个控件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 属性。
原文摘自: