【问题标题】:Avalonia: Binding Command Property to UserControlAvalonia:将命令属性绑定到 UserControl
【发布时间】:2020-04-30 19:22:42
【问题描述】:

所以我创建了一个自定义按钮控件,我们称之为MyButton,使用Avalonia。 MyButton 是几个控件的集合,包括一个看起来像这样的Avalonia.Controls.Button (MyButton.xaml):

<Border xmlns="https://github.com/avaloniaui"
        .....
        x:Class="myProject.myControls.MyButton">
  <Button x:Name="button"
          Background="Transparent"
          ....
          BorderThickness="0">
    <Panel >
      .....
    </Panel>
  </Button>
</Border>

(是的,我的自定义控件继承自 Avalonia.Controls.Border 而不是 Avalonia.Controls.UserControl

我的计划是将按钮Command 属性(具有x:Name="button" 属性的那个)进一步向上传递,并使其可通过MyButton 访问。

所以当我想在MainWindow.xaml 中使用MyButton 时,我可以做到以下几点:

<Window ... >
   <Design.DataContext>
        <vm:MainWindowViewModel/>
   </Design.DataContext>
   <myControls:MyButton Command="{Binding MyButton_Click}"/>
</Window>

视图模型MainWindowViewModel.cs 如下所示:

public partial class MainWindowViewModel : ViewModelBase
{
    public void MyButton_Click()
    {
         // do stuff...
    }
}

我在MyButton.xaml.cs 中尝试这样做的方式如下:

public class MyButton : Border
{
    private readonly Button button;

    public MyButton()
    {
        InitializeComponent();
        button = this.FindControl<Button>("button");
    }

    private void InitializeComponent()
    {
        AvaloniaXamlLoader.Load(this);
    }

    public static readonly StyledProperty<ICommand> CommandProperty =
        AvaloniaProperty.Register<MyButton, ICommand>(nameof(Command));


    public ICommand Command
    {
        get { return GetValue(CommandProperty); }
        set
        { // this setter is never executed as can be seen when running with debugger attached
            if (button != null) 
            {
                button.Command = value;
                SetValue(CommandProperty, value);
            }
            else
            {
                Debug.WriteLine("MyButton error: unable to set Command: control not initialized!");
            }
        }
    }
}

但是,当运行应用程序并单击按钮时,目标方法MyButton_Click 永远不会执行。附加调试器,似乎MyButton.Command setter 也从未执行过,我认为这是由于不正确的绑定? (调试控制台上没有绑定错误或与此相关的任何内容)

经过几个小时的反复试验,我找到了一种解决方法,即在 button 元素上使用反射和自定义 OnClick() 事件处理程序。它可以工作,但有点难看,需要一个静态目标方法,所以我的问题是:

如何正确地将 UserControl 上的 Command 绑定到主窗口的 ViewModel 中包含的方法?

另外:我的基于反射的方法是否也可行? (我假设 Avalonia 绑定也以某种方式基于反射?)

【问题讨论】:

    标签: c# wpf mvvm data-binding avaloniaui


    【解决方案1】:

    不要对样式属性使用 getter 和 setter,它们不会在通过绑定、样式或动画更改属性时被调用(对于 WPF、UWP 和 Xamarin.Forms 也是如此)。相反,您需要通过&lt;Button Command="{Binding $parent[myControls:MyButton]}" /&gt;(首选)绑定嵌套按钮的命令,或者订阅来自静态构造函数的属性更改通知,如原始Buttondoes

    更多关于依赖属性(其工作方式与 Avalonia 中的 StyledProperty 大体相同):https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/dependency-properties-overview

    【讨论】:

    • 我明白了。我实际上查看了它是如何在原始Button(您也链接的那个)的实现中完成的,并最终使用了DirectProperty,就像这样:public static readonly DirectProperty&lt;MyButton, ICommand&gt; CommandProperty = AvaloniaProperty.RegisterDirect&lt;MyButton, ICommand&gt;(nameof(Command), button =&gt; button.Command, (button, command) =&gt; button.Command = command, enableDataValidation: true); 修复了它。由于我对 avalonia 不太熟悉,我想知道这是否也有效,或者这种方法还有其他我不知道的缺点吗?
    • 直接属性用于不需要优先值系统的情况(即属性将始终具有一个值)。您可以在此处阅读有关直接属性的更多信息:avaloniaui.net/docs/authoring-controls/defining-properties
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-08
    • 1970-01-01
    • 1970-01-01
    • 2016-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多