locked
AppBarButton, Command, and CommandParameter

    Question

  • Hi,

    I have a simple AppBarButton in a CommandBar:

    <AppBarButton Icon="Copy" Label="Copy" 
                  Command="{Binding CopyCommand, Source={StaticResource Main}}" 
                  CommandParameter="{Binding ElementName=TestTextBox, Path=Text}"
                  />
    ...
    <TextBox x:Name="TestTextBox" />
    

    The static resource Main is my ViewModel that defines the CopyCommand (using MVVM Light):

    private RelayCommand<string> copyCommand;
    public RelayCommand<string> CopyCommand
    {
        get
        {
            return copyCommand
                ?? (copyCommand = new RelayCommand<string>(
                testString =>
                {
                    string msg = testString;
                },
                // CanExecute
                testString =>
                {
                    return !String.IsNullOrWhiteSpace(testString);
                }
                ));
        }
    }

    The problem is that the Copy AppBarButton is always disabled ("greyed out") despite of the CanExecute part not being called at all. When I comment out the CanExecute part, I can click the button but the testString parameter is always null regardless of the text entered to the TestTextBox.

    The above code works perfectly fine with the Button control. Is it something wrong with the AppBarButton or am I doing something wrong?

    Thanks,

    Leszek


    Wiki: wbswiki.com
    Website: www.wisenheimerbrainstorm.com

    Tuesday, January 06, 2015 5:37 PM

All replies

  • >>The problem is that the Copy AppBarButton is always disabled ("greyed out") despite of the CanExecute part not being called at all. When I comment out the CanExecute part, I can click the button but the testString parameter is always null regardless of the text entered to the TestTextBox.

    This means that your binding doesn't work. You need to make sure that {StaticResource Main} references the correct instance of the correct view model class.

    The following code works as expected, please try it out yourself and you will see:

    public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
                this.DataContext = this;
            }
    
            private RelayCommand<string> copyCommand;
            public RelayCommand<string> CopyCommand
            {
                get
                {
                    return copyCommand
                        ?? (copyCommand = new RelayCommand<string>(
                        testString =>
                        {
                            string msg = testString;
                        }
                        // CanExecute
                        ,testString =>
                        {
                            return !String.IsNullOrWhiteSpace(testString);
                        }
                        ));
                }
            }
    }
    

    <Page
        x:Class="App9.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:App9"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    
            <AppBarButton Icon="Copy" Label="Copy" 
                  Command="{Binding CopyCommand}" 
                  CommandParameter="{Binding ElementName=TestTextBox, Path=Text}"
                  />
    
            <TextBox x:Name="TestTextBox" />
    ...
    

    >>Is it something wrong with the AppBarButton or am I doing something wrong?
    No, there is nothing wrong with the AppBarButton. It is your binding that fails.

    Please remember to mark helpful posts as answer and/or helpful.

    Tuesday, January 06, 2015 6:54 PM
  • Hi Magnus,

    Thanks for your response.

    I have tried your code but it works exactly the same as my code - the AppBarButton is greyed out and CanExecute is not called at all.

    I'm pretty sure my binding is fine because the Main object is instantiated in App.xaml. Also, the code works perfectly fine with the old good Button control. That's why I thought there was something wrong with the AppBarButton.

    I can't understand why your code works as expected on your end. Are you using RelayCommand from the MVVM Light toolkit (the GalaSoft.MvvmLight.Command namespace)? Also, I'm using Visual Studio 2013 and the app targets Windows 8.1

    Thanks,

    Leszek


    Wiki: wbswiki.com
    Website: www.wisenheimerbrainstorm.com

    Tuesday, January 06, 2015 7:29 PM
  • It seems that AppBarButton can't reference Bindings using ElementName.

    Sorry Alexandre, I misremembered the details.

    There isn't a way to use an ElementName binding from the appbar to elements on the page.

    Setting the DataContext to the page will allow binding to the page. This is the common case used for things like Command binding. You could expose a property on the page which returns visibility information based on the GridView's selections.

    source

    I solved this issue by setting the CommandBar.DataContext to my ViewModel, via codebehind.
    That it usually matches with the Page.DataContext or the DataContext of an inner view in the page.


    Tommaso Scalici

    Friday, May 01, 2015 6:11 PM