1 如果逻辑里的属性与控件的属性类型不匹配,要实现相应的IValueConverter
在这个例子里, 我把int型的Value绑定到TextBox的Text,int到string不能直接绑定,因此要实现一个Int2StringConverter,并在绑定时指定。否则不会显示值。
<TextBox Text="{TemplateBinding Value, Converter={StaticResource Int2StringConverter}}"/>
2 Template与控件Logic务必分离
这里的分离是指:Logic不应知道具体的控件名,Logic只暴露依赖属性(包括属性+命令),Template负责绑定属性。这种分离的好处是:如果用户不喜欢你的Template,自己再定制一个,只需绑定到同样的属性+命令,即可实现控件的行为。否则用户就无法改写Template了。
错误的实现方式
private Button upBtn;
public override void OnApplyTemplate()
{
upBtn = (Button)this.Template.FindName("btnUp", this);
upBtn.Click = btn_Click;
}
这样写,就把Logic和Template绑死了。
正确的实现方式
//后台定义UpCommandProperty,实现为DelegateCommand或RoutedCommand,前台Template去绑定
public static readonly DependencyProperty UpCommandProperty = DependencyProperty.Register("UpCommand", typeof(ICommand), typeof(UpDownNumeric));
<Button Command="{TemplateBinding UpCommand}"/>
3 希望模板中的Button能执行CustonControl中某些特定的逻辑
对于这种情况,有两种解决方法:TemplatePartAttribute和Command.
TemplatePartAttribute就是对UI中的元素命名, 然后在后台寻找此元素进行相应的操作.
很可惜, 这会使得UI与逻辑耦合, 这与CustomControl的初衷相悖.当外部程序改写Template时,很有可能失去作用.
Command则十分可靠, 因为它能使UI和逻辑分离. 外部改写UI后, 只需对相应的元素重新绑定内置的Command就可以正常地工作.
下面为大家如何内置Command和如何进行绑定.
在下面的后台代码中, 对TestCommand进行声明和初始化.
然后在静态构造函数中通过CommandManager.RegisterClassCommandBinding(Type,CommandBinding)的方法进行类绑定(当然, 你也可以在构造函数中使用公共的CommandBindings集合,但这并不可靠,因为他人使用此控件时可以随意修改CommandBindings)