我有大量的按钮,它们具有基于键字符串的相同绑定模式。我想我可以通过制作一个自定义控件来保存一些代码重复,该控件接受该字符串并相应地设置所有绑定。我想出了以下代码:
public class StateTransitionButton : Button
{
public string StateTransition
{
get { return (string)this.GetValue(StateTransitionProperty); }
set { this.SetValue(StateTransitionProperty, value); }
}
public static readonly DependencyProperty StateTransitionProperty =
DependencyProperty.Register("MyProperty", typeof(string), typeof(StateTransitionButton), new PropertyMetadata(null, OnTransitionChanged));
private static void OnTransitionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is StateTransitionButton button && e.NewValue is string key)
{
button.CommandParameter = key;
Binding commandBinding = new("ButtonClicked");
commandBinding.Source = button.DataContext;
_ = button.SetBinding(CommandProperty, commandBinding);
button.CommandParameter = key;
Binding visibilityBinding = new("CurrentState")
{
Converter = new UIStateToVisibilityConverter(),
ConverterParameter = key
};
visibilityBinding.Source = button.DataContext;
_ = button.SetBinding(VisibilityProperty, visibilityBinding);
Binding tooltipBinding = new("CurrentState")
{
Converter = new UIStateToTooltipConverter(),
ConverterParameter = key
};
tooltipBinding.Source = button.DataContext;
_ = button.SetBinding(ToolTipProperty, tooltipBinding);
}
}
}
转换器已经在旧代码中使用,并按预期工作。在上面的代码中,绑定似乎没有正确设置。当我在snoop中检查它们时,命令绑定有一个错误(我从未想过如何从snoop中获取可用的错误文本(,可见性仍然是默认值,而不是绑定,工具提示属性是不可检查的。
更新:我在写完它的时候就发现了这一点。无论如何,我都会发布它并自己回答,因为我找不到任何关于如何在自定义控件内设置绑定的清晰示例,其他人可能会觉得我的解决方案很有用。如果我错过了一个更好的,请把这个标记为副本。
因此,StateTransition属性是在datacontext之前设置的。这意味着所有绑定都绑定到了null。修复方法是侦听DataContextChanged事件并重新绑定。无论如何,即使原始代码已经工作,这也是更正确的,因为否则它将无法处理数据上下文的更改。
工作示例:
public class StateTransitionButton : Button
{
public StateTransitionButton()
{
this.DataContextChanged += this.OnDataContextChanged;
}
public string StateTransition
{
get { return (string)this.GetValue(StateTransitionProperty); }
set { this.SetValue(StateTransitionProperty, value); }
}
public static readonly DependencyProperty StateTransitionProperty =
DependencyProperty.Register("MyProperty", typeof(string), typeof(StateTransitionButton), new PropertyMetadata(null, OnTransitionChanged));
private static void OnTransitionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is StateTransitionButton button && e.NewValue is string key)
{
button.SetBindings(key);
}
}
public void SetBindings(string key)
{
this.CommandParameter = key;
Binding commandBinding = new("ButtonClicked");
commandBinding.Source = this.DataContext;
_ = this.SetBinding(CommandProperty, commandBinding);
this.CommandParameter = key;
Binding visibilityBinding = new("CurrentState")
{
Converter = new UIStateToVisibilityConverter(),
ConverterParameter = key
};
visibilityBinding.Source = this.DataContext;
_ = this.SetBinding(VisibilityProperty, visibilityBinding);
Binding tooltipBinding = new("CurrentState")
{
Converter = new UIStateToTooltipConverter(),
ConverterParameter = key
};
tooltipBinding.Source = this.DataContext;
_ = this.SetBinding(ToolTipProperty, tooltipBinding);
}
private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
this.SetBindings(this.StateTransition);
}
}