Avalonia:绑定命令 属性 到 UserControl
Avalonia: Binding Command Property to UserControl
所以我使用 Avalonia 创建了一个自定义按钮控件,我们称之为 MyButton
。 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
.[=32 访问=]
所以当我想在 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 上的命令正确绑定到主 Window 的 ViewModel 中包含的方法?
另外:我基于反射的方法是否也可行? (我假设 Avalonia 绑定也以某种方式基于反射?)
不要对样式化属性使用 getter 和 setter,当通过绑定、样式或动画更改 属性 时,它们 不会 被调用(对于WPF、UWP 和 Xamarin.Forms)。相反,您需要通过 <Button Command="{Binding $parent[myControls:MyButton]}" />
(首选)绑定嵌套 Button 的命令,或者订阅来自静态构造函数的 属性 更改通知,如原始 Button
does.
有关依赖属性的更多信息(其工作方式与 Avalonia 中的 StyledProperty 大致相同):https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/dependency-properties-overview
所以我使用 Avalonia 创建了一个自定义按钮控件,我们称之为 MyButton
。 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
.[=32 访问=]
所以当我想在 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 上的命令正确绑定到主 Window 的 ViewModel 中包含的方法?
另外:我基于反射的方法是否也可行? (我假设 Avalonia 绑定也以某种方式基于反射?)
不要对样式化属性使用 getter 和 setter,当通过绑定、样式或动画更改 属性 时,它们 不会 被调用(对于WPF、UWP 和 Xamarin.Forms)。相反,您需要通过 <Button Command="{Binding $parent[myControls:MyButton]}" />
(首选)绑定嵌套 Button 的命令,或者订阅来自静态构造函数的 属性 更改通知,如原始 Button
does.
有关依赖属性的更多信息(其工作方式与 Avalonia 中的 StyledProperty 大致相同):https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/dependency-properties-overview