像this帖子一样,我想创建一个由多个控件组成的用户控件,这些控件将在我的应用程序中的多个位置使用。就像其他帖子一样,命令栏中的按钮需要触发特定于其用途的事件/命令。这一切都很好,除了在某些情况下,我希望使用
Command
属性在实现控件的页面的 ViewModel
中触发 IRelay 命令,而不是使用 Click
事件。我使用按钮的 XAML Command
属性碰壁了。
我的做法可能完全错误,但这就是我所拥有的和我陷入困境的地方。
用于实现自定义控件的
Page
XAML 绑定到 ViewModel
中的 IRelay 命令。未找到用户控件后面代码中的 ShowPropertiesCommand
IRelay 命令。
<corecontrols:MyTreeView
...
ShowPropertiesCommand="{x:Bind ViewModel.ShowPropertiesCommand}"
TreeViewItemSource="{x:Bind ViewModel.Nodes, Mode=OneWay}" />
UserControl
XAML 绑定到后面代码中的 ShowPropertiesCommand IRelay 命令。
<UserControl x:Class="Core.UI.Controls.MyTreeView" ...>
...
<CommandBar>
...
<AppBarElementContainer>
<Button
x:Name="CB_NodeProperties"
Command="{x:Bind ShowPropertiesCommand}"
... />
</AppBarElementContainer>
</CommandBar>
...
</UserControl>
用户控件代码后面的代码。执行 ExecuteShowPropertiesCommand 是我陷入困境的另一个地方。如何让实现在实现用户控件的页面的 ViewModel 中运行命令?
public MyTreeView()
{
this.InitializeComponent();
ShowPropertiesCommand = new RelayCommand<object>(ExecuteShowPropertiesCommand);
}
public IRelayCommand ShowPropertiesCommand;
private void ExecuteShowPropertiesCommand(object obj)
{
//WHAT TO PUT HERE??
}
您应该为此创建一个 DependencyProperty。
让我向您展示一个简单的例子:
**SomeUserControl.xaml.cs
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System.Windows.Input;
namespace WinUIApp1;
public sealed partial class SomeUserControl : UserControl
{
public static readonly DependencyProperty SomeCommandProperty = DependencyProperty.Register(
nameof(SomeCommand),
typeof(ICommand),
typeof(SomeUserControl),
new PropertyMetadata(default));
public SomeUserControl()
{
InitializeComponent();
}
public ICommand SomeCommand
{
get => (ICommand)GetValue(SomeCommandProperty);
set => SetValue(SomeCommandProperty, value);
}
}
**SomeUserControl.xaml
<UserControl
x:Class="WinUIApp1.SomeUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:WinUIApp1"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<CommandBar>
<AppBarElementContainer>
<Button
Command="{x:Bind SomeCommand, Mode=OneWay}"
Content="Click" />
</AppBarElementContainer>
</CommandBar>
</UserControl>
然后你可以像这样绑定命令:
**SomePage.xaml
<Page
x:Class="WinUIApp1.SomePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:WinUIApp1"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
<local:SomeUserControl SomeCommand="{x:Bind ViewModel.DoSomeTaskCommand}" />
</Page>
**SomePage.xaml.cs
public sealed partial class SomePage : Page
{
public Shell()
{
InitializeComponent();
}
public SomeViewModel ViewModel { get; } = new();
}
SomePageViewModel.cs
public partial class SomeViewModel : ObservableObject
{
// The CommunityToolkit.Mvvm's source generator
// will generate a 'DoSomeTaskCommand' IRelayCommand for you.
[RelayCommand]
private void DoSomeTask()
{
// Do some task here...
}
}
注意
ObservableObject 和 ObservableProperty 来自 CommunityToolkit.Mvvm NuGet 包。