MVVM 命令绑定到 UWP 工具包汉堡菜单
MVVM command binding to UWP toolkit hamburger menu
我尝试使用 MVVM 模式将 ItemClick
和 OptionItemClick
事件绑定到命令。根据文档 https://developer.microsoft.com/en-us/windows/uwp-community-toolkit/api/microsoft_toolkit_uwp_ui_controls_hamburgermenu there is no Command
I can bind to. So I am thinking to use https://www.nuget.org/packages/Microsoft.Xaml.Behaviors.Uwp.Managed/ 将我的事件触发器附加到命令的包。
我的XAML密码是
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="using:Microsoft.Xaml.Interactivity"
xmlns:ic="using:Microsoft.Xaml.Interactions.Core"
xmlns:localModel="using:App1.Models"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
mc:Ignorable="d">
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<localTemplate:TemplatesResourceDictionary/>
</ResourceDictionary.MergedDictionaries>
<DataTemplate x:Key="DefaultTemplate" x:DataType="localModel:MenuItem">
<Grid Width="240" Height="48" Margin="0,0,0,0" HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="48" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<SymbolIcon Grid.Column="0" Symbol="{x:Bind Icon, Mode=OneWay}" Foreground="White" />
<TextBlock Grid.Column="1" Text="{x:Bind Name, Mode=OneWay}" FontSize="16" VerticalAlignment="Center" Foreground="White" />
</Grid>
</DataTemplate>
</ResourceDictionary>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<controls:HamburgerMenu x:Name="hamburgerMenuControl"
Grid.Row="0"
Grid.Column="0"
PaneBackground="Black"
Foreground="White"
DisplayMode="CompactOverlay"
ItemsSource="{Binding Path=MainMenuItems}"
ItemTemplate="{StaticResource DefaultTemplate}"
OptionsItemsSource="{Binding Path=OptionMenuItems}"
OptionsItemTemplate="{StaticResource DefaultTemplate}"
OptionsItemClick="OnMenuItemClick">
<i:Interaction.Behaviors>
<ic:EventTriggerBehavior EventName="ItemClick">
<ic:InvokeCommandAction Command="{Binding Path=NavigateCommand}" />
</ic:EventTriggerBehavior>
</i:Interaction.Behaviors>
<Frame x:Name="contentFrame" />
</controls:HamburgerMenu>
</Grid>
</Page>
首先代码在VS2017中看起来很搞笑,但是并没有产生编译错误。
其次,当我启动代码并单击菜单项时,生成的代码中抛出异常 App.g.i.cs
还有进一步的消息要求我启动另一个调试器。
A debugger is attached to App1.exe but not configured to debug this
unhandled exception. To debug this exception, detach the current
debugger.
任何线索,将命令绑定到我的视图模型的正确方法是什么?
我在 XAML 中没有看到您的 Page
的 DataContext
设置为您的视图模型,所以我想这是在后面的代码中完成的。
正如 Andrey 提到的那样,将鼠标悬停在 e
参数上或在 Watch window 中检查它的值时,您可以看到实际的异常。我的第一个想法是您的视图模型中的命令类型错误,因为您的 XAML 似乎是正确的。传递给您的视图模型的参数不是绑定到您的 HamburgerMenu
的实际类型,而是 ItemClickedEventArgs
.
这是 DelegateCommand
的代码,但 RelayCommand
(或您使用的任何 ICommand
实现)应该类似。
public DelegateCommand<ItemClickEventArgs> NavigateCommand { get; }
private void OnMenuItemClicked(ItemClickEventArgs args)
{
HamburgerMenuPrismItem menuItem = (HamburgerMenuPrismItem)args.ClickedItem;
_navigationService.Navigate(menuItem.TargetPageToken, null);
}
请注意,HamburgerMenuPrismItem 是我自己的类型,这应该是您绑定到 HamburgerMenu 的类型。
前段时间我已经创建了一个类似的示例(使用 Prism 作为 MVVM 框架),因此您可以在 GitHub.
上自行查看来源
奖励:如果您自己添加了 Microsoft.Xaml.Behaviors.Uwp.Managed,则不需要它(除非您想要指定版本)。您的 HamburgerMenu 需要 Microsoft.Toolkit.Uwp.UI.Controls,它会引入 Microsoft.Toolkit.Uwp.UI.Animations,它本身会引入 Microsoft.Xaml.Behaviors.Uwp.Managed。
我尝试使用 MVVM 模式将 ItemClick
和 OptionItemClick
事件绑定到命令。根据文档 https://developer.microsoft.com/en-us/windows/uwp-community-toolkit/api/microsoft_toolkit_uwp_ui_controls_hamburgermenu there is no Command
I can bind to. So I am thinking to use https://www.nuget.org/packages/Microsoft.Xaml.Behaviors.Uwp.Managed/ 将我的事件触发器附加到命令的包。
我的XAML密码是
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="using:Microsoft.Xaml.Interactivity"
xmlns:ic="using:Microsoft.Xaml.Interactions.Core"
xmlns:localModel="using:App1.Models"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
mc:Ignorable="d">
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<localTemplate:TemplatesResourceDictionary/>
</ResourceDictionary.MergedDictionaries>
<DataTemplate x:Key="DefaultTemplate" x:DataType="localModel:MenuItem">
<Grid Width="240" Height="48" Margin="0,0,0,0" HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="48" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<SymbolIcon Grid.Column="0" Symbol="{x:Bind Icon, Mode=OneWay}" Foreground="White" />
<TextBlock Grid.Column="1" Text="{x:Bind Name, Mode=OneWay}" FontSize="16" VerticalAlignment="Center" Foreground="White" />
</Grid>
</DataTemplate>
</ResourceDictionary>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<controls:HamburgerMenu x:Name="hamburgerMenuControl"
Grid.Row="0"
Grid.Column="0"
PaneBackground="Black"
Foreground="White"
DisplayMode="CompactOverlay"
ItemsSource="{Binding Path=MainMenuItems}"
ItemTemplate="{StaticResource DefaultTemplate}"
OptionsItemsSource="{Binding Path=OptionMenuItems}"
OptionsItemTemplate="{StaticResource DefaultTemplate}"
OptionsItemClick="OnMenuItemClick">
<i:Interaction.Behaviors>
<ic:EventTriggerBehavior EventName="ItemClick">
<ic:InvokeCommandAction Command="{Binding Path=NavigateCommand}" />
</ic:EventTriggerBehavior>
</i:Interaction.Behaviors>
<Frame x:Name="contentFrame" />
</controls:HamburgerMenu>
</Grid>
</Page>
首先代码在VS2017中看起来很搞笑,但是并没有产生编译错误。
其次,当我启动代码并单击菜单项时,生成的代码中抛出异常 App.g.i.cs
还有进一步的消息要求我启动另一个调试器。
A debugger is attached to App1.exe but not configured to debug this unhandled exception. To debug this exception, detach the current debugger.
任何线索,将命令绑定到我的视图模型的正确方法是什么?
我在 XAML 中没有看到您的 Page
的 DataContext
设置为您的视图模型,所以我想这是在后面的代码中完成的。
正如 Andrey 提到的那样,将鼠标悬停在 e
参数上或在 Watch window 中检查它的值时,您可以看到实际的异常。我的第一个想法是您的视图模型中的命令类型错误,因为您的 XAML 似乎是正确的。传递给您的视图模型的参数不是绑定到您的 HamburgerMenu
的实际类型,而是 ItemClickedEventArgs
.
这是 DelegateCommand
的代码,但 RelayCommand
(或您使用的任何 ICommand
实现)应该类似。
public DelegateCommand<ItemClickEventArgs> NavigateCommand { get; }
private void OnMenuItemClicked(ItemClickEventArgs args)
{
HamburgerMenuPrismItem menuItem = (HamburgerMenuPrismItem)args.ClickedItem;
_navigationService.Navigate(menuItem.TargetPageToken, null);
}
请注意,HamburgerMenuPrismItem 是我自己的类型,这应该是您绑定到 HamburgerMenu 的类型。
前段时间我已经创建了一个类似的示例(使用 Prism 作为 MVVM 框架),因此您可以在 GitHub.
上自行查看来源奖励:如果您自己添加了 Microsoft.Xaml.Behaviors.Uwp.Managed,则不需要它(除非您想要指定版本)。您的 HamburgerMenu 需要 Microsoft.Toolkit.Uwp.UI.Controls,它会引入 Microsoft.Toolkit.Uwp.UI.Animations,它本身会引入 Microsoft.Xaml.Behaviors.Uwp.Managed。