简体   繁体   English

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

[英]Binding Command of Button in AppBar does not work

Why does the Command in the following example not execute? 为什么以下示例中的Command不执行?

I have a named Page with an AppBar and a Button in it: 我有一个带有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>

The Command "OkCommand" is defined in the code-behind like this (using MVVM light framework): 命令“OkCommand”在这样的代码隐藏中定义(使用MVVM轻量级框架):

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

There are no binding-errors nor any other hints in the output-window that give me an idea why this does not work. 输出窗口中没有绑定错误也没有任何其他提示让我知道为什么这不起作用。 (Aside: if the button is placed outside the AppBar, everything works fine) (旁白:如果按钮放在AppBar外面,一切正常)

Does anyone have an idea what is wrong here? 有没有人知道这里有什么问题?

There should be no reason for the command binding not working for a button in AppBar if it works for a button elsewhere on the page. 如果它适用于页面上其他位置的按钮,则命令绑定不应该对AppBar中的按钮起作用。

I suspect the problem is related to how DataContext is set. 我怀疑问题与DataContext的设置方式有关。 You should have it set at the page level instead of lower in the control tree. 您应该将它设置在页面级别而不是控制树中的较低级别。 All the other buttons are inside the top content control of the page while the AppBar is outside of it causing the binding not to work if DataContext is set at the top content control or below. 所有其他按钮都位于页面的顶级内容控件内,而AppBar位于其外部,如果DataContext设置在顶级内容控件或更低位置,则绑定不起作用。

You can try it with the following working example: 您可以使用以下工作示例进行尝试:

MainPage.xaml : 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 : 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 : MainPage.xaml.cs

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

I know this question is for Windows RT/8, however I ran into this same problem with Universal Apps (UWP) and I found the solution using the new {x:Bind}. 我知道这个问题适用于Windows RT / 8,但我遇到了与Universal Apps(UWP)相同的问题,我发现使用新的{x:Bind}的解决方案。 Note, by default x:Bind will map to OneTime instead of {Binding} where it was OneWay. 注意,默认情况下x:Bind将映射到OneTime而不是{Binding},它是OneWay。

I found this pattern while watching one of the MSDN Windows 10 Developer videos on the new XAML Bind. 我在新XAML Bind上观看一个MSDN Windows 10开发人员视频时发现了这种模式。

Modify YourPage.cs 修改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;
        };
    }
}

Modify YourPageViewModel.cs 修改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()
    {

    }
}

Modify YourPage.xaml 修改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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM