繁体   English   中英

WPF:从 c# 代码创建具有自动绑定的自定义按钮

[英]WPF: Creating a custom button with automatic bindings from c# code

我有大量基于键字符串具有相同绑定模式的按钮。 我想我可以通过制作一个采用该字符串并相应地设置所有绑定的自定义控件来节省一些代码重复。 我想出了以下代码:

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 属性是在数据上下文之前设置的。 这意味着所有绑定都绑定到 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);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM