0

所以我创建了一个自定义按钮控件,我们称之为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.

因此,当我想在中使用MyButton时,MainWindow.xaml我将能够执行以下操作:

<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也从未执行过设置器,我认为这是由于不正确的绑定?(调试控制台上没有绑定错误或与此相关的任何内容)

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

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

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

4

1 回答 1

1

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

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

于 2020-04-30T20:08:58.447 回答