2013-01-16 51 views
4

为什么以下示例中的命令不能执行?AppBar中按钮的绑定命令不起作用

我在它与AppBar一个名为页面和按钮:

<Page 
    x:Class="App13.MainPage" 
    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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d" 
    x:Name="myPage" 
    > 
    <Page.BottomAppBar> 
     <AppBar> 
      <Button Content="OK" Command="{Binding OkCommand, ElementName=myPage}" /> 
     </AppBar> 
    </Page.BottomAppBar> 
</Page> 

命令“OkCommand”在后台代码的定义如下(使用MVVM光框架):

public RelayCommand OkCommand 
{ 
    get 
    { 
     return m_OkCommand 
      ?? (m_OkCommand = new RelayCommand(
            async() => 
            { 
             await new MessageDialog("OkCommand").ShowAsync(); 
            })); 
    } 
} 

输出窗口中没有绑定错误或任何其他提示,让我知道为什么这不起作用。 (另外:如果按钮放在AppBar之外,一切正常)

有没有人有一个想法这里有什么错?

回答

3

如果它适用于页面上其他位置的按钮,那么命令绑定不应该适用于AppBar中的按钮。

我怀疑问题与如何设置DataContext有关。您应该将它设置在页面级别而不是控制树中的较低位置。所有其他按钮位于页面的顶部内容控件内,而AppBar位于页面的外部,导致如果DataContext设置在顶部内容控件或更低位置,则绑定不起作用。

您可以用下面的工作例尝试它:

MainPage.xaml

<common:LayoutAwarePage 
    x:Class="App16.MainPage" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="using:App16" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:common="using:App16.Common" 
    x:Name="MyPageName" 
    mc:Ignorable="d"> 

    <StackPanel x:Name="MainGrid" Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> 
     <Button Content="Ok" Command="{Binding OkCommand}" /> 
    </StackPanel> 

    <Page.BottomAppBar> 
     <AppBar x:Name="bottomAppBar" Padding="10,10,10,10" > 
      <StackPanel Orientation="Horizontal" HorizontalAlignment="Right"> 
       <Button Style="{StaticResource SkipBackAppBarButtonStyle}" Command="{Binding OkCommand}" > 
       </Button> 
      </StackPanel> 
     </AppBar> 
    </Page.BottomAppBar> 
</common:LayoutAwarePage> 

ViewModel.cs

public class ViewModel 
{ 
    private RelayCommand _okCommand; 
    public RelayCommand OkCommand 
    { 
     get 
     { 
      return _okCommand 
       ?? (_okCommand = new RelayCommand(
             async _ => 
             { 
              await new MessageDialog("OkCommand").ShowAsync(); 
             })); 
     } 
    } 
} 

MainPage.xaml.cs

public sealed partial class MainPage : LayoutAwarePage 
{ 
    public MainPage() 
    { 
     this.InitializeComponent(); 
     DataContext = new ViewModel(); 
    } 
} 
+0

感谢您的例子。使用明确的ViewModel工作正常(并给我至少一些解决方法)。 但是,我应该对我的问题更加具体:如果OkCommand是在代码隐藏中定义的,那么无法通过“{Binding Path = OkCommand,ElementName pageRoot}”绑定到命名元素。 我再次对此非常满意。如果在页面XAML中定义了“pageRoot”的绑定,但在AppBar-XAML内使用绑定时不起作用。奇怪。对此有何想法? – CEvenSharper

+2

@CEvenSharper看起来'AppBar'元素看不到页面的其余部分,因此'ElementName'绑定不起作用。既然你在代码后面有'Command',你可以直接使用'Click'事件处理程序而不是'Command',除非你还需要'CanExecute'来禁用它。或者你可以创建一个单独的'ViewModel',我通常找到一个更好的主意,而不是一个解决方法。 –

0

我知道这个问题是针对Windows RT/8的,但是我遇到了与Universal Apps(UWP)相同的问题,并且我找到了使用新的{x:Bind}的解决方案。请注意,默认情况下,x:Bind将映射到OneTime,而不是{Binding},它是OneWay的地方。

我在新的XAML Bind上观看MSDN Windows 10 Developer视频之一时发现了这种模式。

修改YourPage.cs

public sealed partial class YourPage : Page 
{ 
    public ViewModels.YourPageViewModel ViewModel { get; set; } 

    public YourPage() 
    { 
     this.InitializeComponent(); 

     if (DesignMode.DesignModeEnabled) return; 

     this.DataContextChanged += (s, e) => 
     { 
      ViewModel = DataContext as ViewModels.YourPageViewModel; 
     }; 
    } 
} 

修改YourPageViewModel.cs

public class YourPageViewModel : ViewModelBase 
{ 
    private ICommand newFunctionCommand; 
    public ICommand NewFunctionCommand { get { return newFunctionCommand; } } 

    public YourPageViewModel() 
    { 
     if (DesignMode.DesignModeEnabled) return; 

     if (newFunctionCommand == null) 
      newFunctionCommand = new ICommand(new Action(NewFunction)); 
    } 

    protected void NewFunction() 
    { 

    } 
} 

修改YourPage.xaml

<Page.DataContext> 
    <vm:YourViewModel x:Name="YourVM" /> 
</Page.DataContext> 

<Page.BottomAppBar> 
    <CommandBar ClosedDisplayMode="Compact"> 
     <AppBarButton x:Name="AddAppBarButton" IsCompact="True" 
         Label="New" Icon="Add" 
         Command="{x:Bind ViewModel.NewFunctionCommand, Mode=OneWay}" /> 
    </CommandBar> 
</Page.BottomAppBar>