AppBar中Button的绑定命令不起作用

时间:2013-01-16 18:41:53

标签: c# binding winrt-xaml

为什么以下示例中的命令不执行?

我有一个带有AppBar和Button的命名页面:

   <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外面,一切正常)

有没有人知道这里有什么问题?

2 个答案:

答案 0 :(得分: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();
    }
}

答案 1 :(得分:0)

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

我在新XAML Bind上观看某个MSDN Windows 10开发人员视频时发现了这种模式。

修改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>