Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Avalonia:将命令属性绑定到UserControl_C#_Wpf_Mvvm_Data Binding_Avaloniaui - Fatal编程技术网

C# Avalonia:将命令属性绑定到UserControl

C# Avalonia:将命令属性绑定到UserControl,c#,wpf,mvvm,data-binding,avaloniaui,C#,Wpf,Mvvm,Data Binding,Avaloniaui,因此,我使用Avalonia创建了一个自定义按钮控件,我们称之为MyButtonMyButton是多个控件的集合,包括一个Avalonia.controls.Button看起来像这样(MyButton.xaml): 其中视图模型MainWindowViewModel.cs如下所示: public partial class MainWindowViewModel : ViewModelBase { public void MyButton_Click() { /

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

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

public partial class MainWindowViewModel : ViewModelBase
{
    public void MyButton_Click()
    {
         // do stuff...
    }
}
我在
MyButton.xaml.cs
中尝试这样做的方式如下:

<Window ... >
   <Design.DataContext>
        <vm:MainWindowViewModel/>
   </Design.DataContext>
   <myControls:MyButton Command="{Binding MyButton_Click}"/>
</Window>
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:边框
{
私人只读按钮;
公共MyButton()
{
初始化组件();
button=此.FindControl(“按钮”);
}
私有void InitializeComponent()
{
avalonixamlloader.Load(此);
}
公共静态只读样式属性CommandProperty=
寄存器(nameof(Command));
公共ICommand命令
{
获取{返回GetValue(CommandProperty);}
设置
{//此setter永远不会执行,因为在连接了调试器的情况下运行时可以看到
如果(按钮!=null)
{
按钮。命令=值;
SetValue(CommandProperty,value);
}
其他的
{
WriteLine(“MyButton错误:无法设置命令:控件未初始化!”);
}
}
}
}
但是,当运行应用程序并单击按钮时,永远不会执行目标方法
MyButton\u Click
。附加调试器看起来像是
MyButton.Command
setter也从未执行过,我想这可能是由于绑定不正确造成的?(调试控制台上没有绑定错误或与此相关的任何内容)

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

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


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

不要对样式化属性使用getter和setter,当通过绑定、样式或动画更改属性时,不会被调用(对于WPF、UWP和Xamarin.Forms也是如此)。相反,您需要通过
(更可取)绑定嵌套按钮的命令,或者像原始的
按钮一样从静态构造函数订阅属性更改通知


更多关于依赖属性的信息(其工作方式与Avalonia中的StyledProperty基本相同):

我明白了。实际上,我查看了它是如何在原始
按钮(您也链接的按钮)的实现中完成的,并最终使用了
DirectProperty
,如下所示:
公共静态只读DirectProperty CommandProperty=AvaloniProperty.RegisterDirect(nameof(Command),Button=>Button.Command,(Button,Command)=>按钮。命令=命令,enableDataValidation:true)哪个修复了它。由于我对avalonia不太熟悉,我想知道这是否也适用,或者这种方法是否存在我不知道的任何其他缺点?直接属性用于不需要优先价值体系的情况(即,该属性始终具有一个值)。您可以在此处阅读有关直接属性的更多信息:
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!");
            }
        }
    }
}