CheckBox DelegateCommand 未触发
CheckBox DelegateCommand not firing
我看到过许多类似的问题,但我认为我的问题可能不同,值得发布。
我只是将示例 Azure 移动服务应用程序迁移到 Windows 10 UWP 并尝试保留所有 MVVM。我有一个 ListView
有一个 DataTemplate
看起来像这样:
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Name="CheckBoxComplete"
Command="{Binding ElementName=ViewModel, Path=UpdateCommand}"
CommandParameter="{Binding}"
Margin="10,5"
VerticalAlignment="Center"
Content="{Binding Text}"
IsChecked="{Binding Complete,
Mode=TwoWay}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
一切编译正常,但 UpdateCommand
没有触发。我设置了一个断点以确保正确的值将作为 CommandParameter
传递,但 Command
未触发。是否可以在 DataTemplate
内的 CheckBox
上使用 DelegateCommand
?
或者我必须使用附加行为来实现这样的目标吗?
编辑
原来的 CheckBox
看起来像这样,代码隐藏中有点击事件处理程序:
<CheckBox Name="CheckBoxComplete"
IsChecked="{Binding Complete, Mode=TwoWay}"
Checked="CheckBoxComplete_Checked"
Content="{Binding Text}"
Margin="10,5" VerticalAlignment="Center" />
EDIT2
根据要求发布整个 XAML:
<Page x:Class="MyMoney10.Views.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:behaviors="using:Template10.Behaviors"
xmlns:common="using:MyMoney10.Common"
xmlns:controls="using:Template10.Controls"
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:local="using:MyMoney10.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:models="using:MyMoney10.Models"
xmlns:vm="using:MyMoney10.ViewModels"
mc:Ignorable="d">
<Page.DataContext>
<vm:MainPageViewModel x:Name="ViewModel" />
</Page.DataContext>
<RelativePanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<RelativePanel.ChildrenTransitions>
<TransitionCollection>
<EntranceThemeTransition />
</TransitionCollection>
</RelativePanel.ChildrenTransitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="AdaptiveVisualStateGroup">
<VisualState x:Name="VisualStateNarrow">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource NarrowMinWidth}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<!-- TODO: change properties for narrow view -->
<!--<Setter Target="StateTextBox.Text" Value="Narrow Visual State" />-->
</VisualState.Setters>
</VisualState>
<VisualState x:Name="VisualStateNormal">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource NormalMinWidth}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<!-- TODO: change properties for normal view -->
<!--<Setter Target="StateTextBox.Text" Value="Normal Visual State" />-->
</VisualState.Setters>
</VisualState>
<VisualState x:Name="VisualStateWide">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource WideMinWidth}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<!-- TODO: change properties for wide view -->
<!--<Setter Target="StateTextBox.Text" Value="Wide Visual State" />-->
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<controls:PageHeader x:Name="PageHeader" Text="MyMoney">
<!-- place stretched, across top -->
<RelativePanel.AlignTopWithPanel>True</RelativePanel.AlignTopWithPanel>
<RelativePanel.AlignRightWithPanel>True</RelativePanel.AlignRightWithPanel>
<RelativePanel.AlignLeftWithPanel>True</RelativePanel.AlignLeftWithPanel>
<!-- secondary commands -->
<controls:PageHeader.SecondaryCommands>
<AppBarButton Click="{x:Bind ViewModel.GotoSettings}" Label="Settings" />
<AppBarButton Click="{x:Bind ViewModel.GotoPrivacy}" Label="Privacy" />
<AppBarButton Click="{x:Bind ViewModel.GotoAbout}" Label="About" />
</controls:PageHeader.SecondaryCommands>
</controls:PageHeader>
<controls:Resizer x:Name="ParameterResizer" Margin="16,16,16,0">
<!-- place below page header -->
<RelativePanel.Below>PageHeader</RelativePanel.Below>
<RelativePanel.AlignLeftWithPanel>True</RelativePanel.AlignLeftWithPanel>
<TextBox MinWidth="250"
MinHeight="62"
Header="Parameter to pass"
Text="{Binding Value,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}">
<interactivity:Interaction.Behaviors>
<!-- enable submit on enter key -->
<behaviors:KeyBehavior Key="Enter">
<core:CallMethodAction MethodName="GotoDetailsPage" TargetObject="{Binding}" />
</behaviors:KeyBehavior>
<!-- focus on textbox when page loads -->
<core:EventTriggerBehavior>
<behaviors:FocusAction />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</TextBox>
</controls:Resizer>
<Button x:Name="SubmitButton"
Click="{x:Bind ViewModel.GotoDetailsPage}"
Content="Submit">
<!-- place next to textbox -->
<RelativePanel.RightOf>ParameterResizer</RelativePanel.RightOf>
<RelativePanel.AlignBottomWith>ParameterResizer</RelativePanel.AlignBottomWith>
</Button>
<TextBlock x:Name="StateTextBox"
Margin="16,16,0,0"
Text="Current Visual State">
<!-- place under to textbox -->
<RelativePanel.Below>ParameterResizer</RelativePanel.Below>
<RelativePanel.AlignLeftWith>ParameterResizer</RelativePanel.AlignLeftWith>
</TextBlock>
<Grid>
<RelativePanel.Below>StateTextBox</RelativePanel.Below>
<RelativePanel.AlignLeftWithPanel>True</RelativePanel.AlignLeftWithPanel>
<RelativePanel.AlignRightWithPanel>True</RelativePanel.AlignRightWithPanel>
<RelativePanel.AlignBottomWithPanel>True</RelativePanel.AlignBottomWithPanel>
<Grid Margin="50,50,10,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0"
Grid.ColumnSpan="2"
Margin="0,0,0,20">
<StackPanel>
<TextBlock Margin="0,0,0,6"
FontFamily="Segoe UI Light"
Foreground="#0094ff">
MICROSOFT AZURE MOBILE SERVICES
</TextBlock>
<TextBlock FontFamily="Segoe UI Light"
FontSize="45"
Foreground="Gray">
MyMoney10
</TextBlock>
</StackPanel>
</Grid>
<Grid Grid.Row="1">
<StackPanel>
<common:QuickStartTask Title="Insert a TodoItem"
Description="Enter some text below and click Save to insert a new todo item into your database"
Number="1" />
<StackPanel Margin="72,0,0,0" Orientation="Horizontal">
<TextBox Name="TextInput"
MinWidth="300"
Margin="5" />
<Button Name="ButtonSave"
Command="{x:Bind ViewModel.SaveCommand}"
CommandParameter="{Binding ElementName=TextInput,
Path=Text}"
IsEnabled="{x:Bind ViewModel.SaveEnabled}">
Save
</Button>
</StackPanel>
</StackPanel>
</Grid>
<Grid Grid.Row="1" Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel>
<common:QuickStartTask Title="Query and Update Data"
Description="Click refresh below to load the unfinished TodoItems from your database. Use the checkbox to complete and update your TodoItems"
Number="2" />
<Button Name="ButtonRefresh"
Margin="72,0,0,0"
Click="{x:Bind ViewModel.RefreshCommand}"
IsEnabled="{x:Bind ViewModel.RefreshEnabled}">
Refresh
</Button>
</StackPanel>
<ListView Name="ListItems"
Grid.Row="1"
Margin="62,10,0,0"
ItemsSource="{Binding TodoItems}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Name="CheckBoxComplete"
Margin="10,5"
VerticalAlignment="Center"
Command="{Binding ElementName=ViewModel,
Path=UpdateCommand}"
CommandParameter="{Binding}"
Content="{Binding Text}"
IsChecked="{Binding Complete,
Mode=TwoWay}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Grid>
</Grid>
</RelativePanel>
</Page>
所以绑定到 elementname="viewmodel" 的复选框就是问题所在。因为 viewmodel 不是元素的名称。
因此,请为您的页面命名并将该名称放入绑定中。路径=Datacontext.UpdateCommand
我看到过许多类似的问题,但我认为我的问题可能不同,值得发布。
我只是将示例 Azure 移动服务应用程序迁移到 Windows 10 UWP 并尝试保留所有 MVVM。我有一个 ListView
有一个 DataTemplate
看起来像这样:
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Name="CheckBoxComplete"
Command="{Binding ElementName=ViewModel, Path=UpdateCommand}"
CommandParameter="{Binding}"
Margin="10,5"
VerticalAlignment="Center"
Content="{Binding Text}"
IsChecked="{Binding Complete,
Mode=TwoWay}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
一切编译正常,但 UpdateCommand
没有触发。我设置了一个断点以确保正确的值将作为 CommandParameter
传递,但 Command
未触发。是否可以在 DataTemplate
内的 CheckBox
上使用 DelegateCommand
?
或者我必须使用附加行为来实现这样的目标吗?
编辑
原来的 CheckBox
看起来像这样,代码隐藏中有点击事件处理程序:
<CheckBox Name="CheckBoxComplete"
IsChecked="{Binding Complete, Mode=TwoWay}"
Checked="CheckBoxComplete_Checked"
Content="{Binding Text}"
Margin="10,5" VerticalAlignment="Center" />
EDIT2
根据要求发布整个 XAML:
<Page x:Class="MyMoney10.Views.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:behaviors="using:Template10.Behaviors"
xmlns:common="using:MyMoney10.Common"
xmlns:controls="using:Template10.Controls"
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:local="using:MyMoney10.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:models="using:MyMoney10.Models"
xmlns:vm="using:MyMoney10.ViewModels"
mc:Ignorable="d">
<Page.DataContext>
<vm:MainPageViewModel x:Name="ViewModel" />
</Page.DataContext>
<RelativePanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<RelativePanel.ChildrenTransitions>
<TransitionCollection>
<EntranceThemeTransition />
</TransitionCollection>
</RelativePanel.ChildrenTransitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="AdaptiveVisualStateGroup">
<VisualState x:Name="VisualStateNarrow">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource NarrowMinWidth}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<!-- TODO: change properties for narrow view -->
<!--<Setter Target="StateTextBox.Text" Value="Narrow Visual State" />-->
</VisualState.Setters>
</VisualState>
<VisualState x:Name="VisualStateNormal">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource NormalMinWidth}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<!-- TODO: change properties for normal view -->
<!--<Setter Target="StateTextBox.Text" Value="Normal Visual State" />-->
</VisualState.Setters>
</VisualState>
<VisualState x:Name="VisualStateWide">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource WideMinWidth}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<!-- TODO: change properties for wide view -->
<!--<Setter Target="StateTextBox.Text" Value="Wide Visual State" />-->
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<controls:PageHeader x:Name="PageHeader" Text="MyMoney">
<!-- place stretched, across top -->
<RelativePanel.AlignTopWithPanel>True</RelativePanel.AlignTopWithPanel>
<RelativePanel.AlignRightWithPanel>True</RelativePanel.AlignRightWithPanel>
<RelativePanel.AlignLeftWithPanel>True</RelativePanel.AlignLeftWithPanel>
<!-- secondary commands -->
<controls:PageHeader.SecondaryCommands>
<AppBarButton Click="{x:Bind ViewModel.GotoSettings}" Label="Settings" />
<AppBarButton Click="{x:Bind ViewModel.GotoPrivacy}" Label="Privacy" />
<AppBarButton Click="{x:Bind ViewModel.GotoAbout}" Label="About" />
</controls:PageHeader.SecondaryCommands>
</controls:PageHeader>
<controls:Resizer x:Name="ParameterResizer" Margin="16,16,16,0">
<!-- place below page header -->
<RelativePanel.Below>PageHeader</RelativePanel.Below>
<RelativePanel.AlignLeftWithPanel>True</RelativePanel.AlignLeftWithPanel>
<TextBox MinWidth="250"
MinHeight="62"
Header="Parameter to pass"
Text="{Binding Value,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}">
<interactivity:Interaction.Behaviors>
<!-- enable submit on enter key -->
<behaviors:KeyBehavior Key="Enter">
<core:CallMethodAction MethodName="GotoDetailsPage" TargetObject="{Binding}" />
</behaviors:KeyBehavior>
<!-- focus on textbox when page loads -->
<core:EventTriggerBehavior>
<behaviors:FocusAction />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</TextBox>
</controls:Resizer>
<Button x:Name="SubmitButton"
Click="{x:Bind ViewModel.GotoDetailsPage}"
Content="Submit">
<!-- place next to textbox -->
<RelativePanel.RightOf>ParameterResizer</RelativePanel.RightOf>
<RelativePanel.AlignBottomWith>ParameterResizer</RelativePanel.AlignBottomWith>
</Button>
<TextBlock x:Name="StateTextBox"
Margin="16,16,0,0"
Text="Current Visual State">
<!-- place under to textbox -->
<RelativePanel.Below>ParameterResizer</RelativePanel.Below>
<RelativePanel.AlignLeftWith>ParameterResizer</RelativePanel.AlignLeftWith>
</TextBlock>
<Grid>
<RelativePanel.Below>StateTextBox</RelativePanel.Below>
<RelativePanel.AlignLeftWithPanel>True</RelativePanel.AlignLeftWithPanel>
<RelativePanel.AlignRightWithPanel>True</RelativePanel.AlignRightWithPanel>
<RelativePanel.AlignBottomWithPanel>True</RelativePanel.AlignBottomWithPanel>
<Grid Margin="50,50,10,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0"
Grid.ColumnSpan="2"
Margin="0,0,0,20">
<StackPanel>
<TextBlock Margin="0,0,0,6"
FontFamily="Segoe UI Light"
Foreground="#0094ff">
MICROSOFT AZURE MOBILE SERVICES
</TextBlock>
<TextBlock FontFamily="Segoe UI Light"
FontSize="45"
Foreground="Gray">
MyMoney10
</TextBlock>
</StackPanel>
</Grid>
<Grid Grid.Row="1">
<StackPanel>
<common:QuickStartTask Title="Insert a TodoItem"
Description="Enter some text below and click Save to insert a new todo item into your database"
Number="1" />
<StackPanel Margin="72,0,0,0" Orientation="Horizontal">
<TextBox Name="TextInput"
MinWidth="300"
Margin="5" />
<Button Name="ButtonSave"
Command="{x:Bind ViewModel.SaveCommand}"
CommandParameter="{Binding ElementName=TextInput,
Path=Text}"
IsEnabled="{x:Bind ViewModel.SaveEnabled}">
Save
</Button>
</StackPanel>
</StackPanel>
</Grid>
<Grid Grid.Row="1" Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel>
<common:QuickStartTask Title="Query and Update Data"
Description="Click refresh below to load the unfinished TodoItems from your database. Use the checkbox to complete and update your TodoItems"
Number="2" />
<Button Name="ButtonRefresh"
Margin="72,0,0,0"
Click="{x:Bind ViewModel.RefreshCommand}"
IsEnabled="{x:Bind ViewModel.RefreshEnabled}">
Refresh
</Button>
</StackPanel>
<ListView Name="ListItems"
Grid.Row="1"
Margin="62,10,0,0"
ItemsSource="{Binding TodoItems}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Name="CheckBoxComplete"
Margin="10,5"
VerticalAlignment="Center"
Command="{Binding ElementName=ViewModel,
Path=UpdateCommand}"
CommandParameter="{Binding}"
Content="{Binding Text}"
IsChecked="{Binding Complete,
Mode=TwoWay}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Grid>
</Grid>
</RelativePanel>
</Page>
所以绑定到 elementname="viewmodel" 的复选框就是问题所在。因为 viewmodel 不是元素的名称。
因此,请为您的页面命名并将该名称放入绑定中。路径=Datacontext.UpdateCommand