Question

I intended to disable and enable the Buttons outside the TabControl, just like those inside the TabItem when the current tab is changed. But the CommandBindings of the TabItem do not seem to impact "up" the visual tree. What is the right way to do this?

With this XAML:

<Window x:Class="WpfApplication10.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication10"
    Title="MainWindow" Height="350" Width="525">
<StackPanel>
    <Button Content="MyCommand1" Command="local:MainWindow.MyCommand1" />
    <Button Content="MyCommand2" Command="local:MainWindow.MyCommand2" />
    <TabControl>
        <TabItem Header="tabItem1" Name="tabItem1">
            <TabItem.CommandBindings>
                <CommandBinding Command="local:MainWindow.MyCommand1" 
                                Executed="ExecuteMyCommand" />
            </TabItem.CommandBindings>
            <StackPanel>
                <Button Content="MyCommand1" Command="local:MainWindow.MyCommand1" />
                <Button Content="MyCommand2" Command="local:MainWindow.MyCommand2" />
            </StackPanel>
        </TabItem>
        <TabItem Header="tabItem2" Name="tabItem2">
            <TabItem.CommandBindings>
                <CommandBinding Command="local:MainWindow.MyCommand2" 
                                Executed="ExecuteMyCommand"/>
            </TabItem.CommandBindings>
            <StackPanel>
                <Button Content="MyCommand1" Command="local:MainWindow.MyCommand1" />
                <Button Content="MyCommand2" Command="local:MainWindow.MyCommand2" />
            </StackPanel>
        </TabItem>
    </TabControl>
</StackPanel>
</Window>

With this Code Behind:

    public static readonly RoutedUICommand MyCommand1 = new RoutedUICommand();
    public static readonly RoutedUICommand MyCommand2 = new RoutedUICommand();
    public MainWindow()
    {
        InitializeComponent();
    }
    private void ExecuteMyCommand(object sender, ExecutedRoutedEventArgs e)
    {
        MessageBox.Show("Hello");
    }
Was it helpful?

Solution

MSFT gave me the correct answer in their WPF forum, here (http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/bb3d1eb1-96fa-4fbc-beda-799613acb9f7)

<StackPanel>
     <StackPanel FocusManager.IsFocusScope="True">
         <Button Content="MyCommand1" Command="local:Window8.MyCommand1" />
         <Button Content="MyCommand2" Command="local:Window8.MyCommand2" />
     </StackPanel>
     <TabControl>
         <TabItem Header="tabItem1" Name="tabItem1">
             <TabItem.CommandBindings>
                 <CommandBinding Command="local:Window8.MyCommand1" Executed="ExecuteMyCommand" />
             </TabItem.CommandBindings>
             <StackPanel>
                 <Button Content="MyCommand1" Command="local:Window8.MyCommand1" />
                 <Button Content="MyCommand2" Command="local:Window8.MyCommand2" />
             </StackPanel>
         </TabItem>
         <TabItem Header="tabItem2" Name="tabItem2">
             <TabItem.CommandBindings>
                 <CommandBinding Command="local:Window8.MyCommand2" Executed="ExecuteMyCommand"/>
             </TabItem.CommandBindings>
             <StackPanel>
                 <Button Content="MyCommand1" Command="local:Window8.MyCommand1" />
                 <Button Content="MyCommand2" Command="local:Window8.MyCommand2" />
             </StackPanel>
         </TabItem>
     </TabControl>
</StackPanel>

OTHER TIPS

Your don't have any code that could disable buttons. You can do it in several ways:

1. Define CanExecute event handler.

<CommandBinding Command="local:MainWindow.MyCommand1" 
        Executed="ExecuteMyCommand" 
        CanExecute="MyCommand_CanExecute"/>

Code behind:

private void MyCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = tabItem1.IsSelected;
}

2. Bind button IsEnabled property to tab item IsSelected property

<Button IsEnabled="{Binding ElementName=tabItem1, Path=IsSelected}" 
        Content="MyCommand1" Command="local:MainWindow.MyCommand1" />

Is this all the code?

You have a special CanExecute defined, that disables the MyCommandsX ?
Or you have a binding on the Enabled Property of the bound buttons, and you implement INotifyPropertyChanged or something?

Or why should they be enabled/disabled in your code sample?
I you ask me, I wouldn't expect the code to disable the buttons..

Update 1:

You could enable the buttons the same way you did it, by adding the command bindings in the surrounding stackpanel for example.

    <StackPanel>
    <StackPanel.CommandBindings>
            <CommandBinding Command="local:MainWindow.MyCommand1"  
                            Executed="ExecuteMyCommand" />
    </StackPanel.CommandBindings>
    <Button Content="MyCommand1" Command="local:MainWindow.MyCommand1" />
    <Button Content="MyCommand2" Command="local:MainWindow.MyCommand2" />
    <TabControl>

You can use the CanExecute part of the command binding to verify the conditions under which the bound buttons enabled. Instead you should handle the command itself I think.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top