Ribbon Button Doesn't Respond to Change in "IsEnabled"

Ribbon for WPF Forum

Posted 10 years ago by Andy Ver Murlen
Version: 9.1.0500
Platform: .NET 3.5
Environment: Windows XP (32-bit)
Avatar
Hi, I have noticed that when a ribbon button has a binding to it's own "IsEnabled" state, the binding does not properly update when "IsEnabled" changes. The most obvious use for this would be to hide/show the button when the command assigned to the button changes it's ability to execute. I am including some code to reproduce the problem. If you run the code and click the "toggle command" button, you will see that the standard WPF button toggle between visible and hidden. However, the ribbon button remains hidden the entire time. Note, that I am using the ribbon button outside of a ribbon for theme consistency.

<Window 
    x:Class="DockingSample.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sample="clr-namespace:DockingSample"
    xmlns:ribbon="clr-namespace:ActiproSoftware.Windows.Controls.Ribbon.Controls;assembly=ActiproSoftware.Ribbon.Wpf30"
    Title="Window1"
    WindowState="Maximized"
    >
    <Window.Resources>
        <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
    </Window.Resources>
    
    <Window.CommandBindings>
        <CommandBinding Command="sample:Window1.MyCommand" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed" />
    </Window.CommandBindings>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        
        <Button
            Margin="3"
            Content="Toggle Command State"
            Click="Button_Click"
            />
        <ribbon:Button
            Margin="3"
            Grid.Row="1"
            Label="Copy"
            Command="sample:Window1.MyCommand"
            Visibility="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled, Converter={StaticResource BooleanToVisibilityConverter}}"
            />
         <Button
            Margin="3"
            Grid.Row="2"
            Content="Copy"
            Command="sample:Window1.MyCommand"
            Visibility="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled, Converter={StaticResource BooleanToVisibilityConverter}}"
            /> 
    </Grid>
</Window>

using System.Windows;
using System.Windows.Input;

namespace DockingSample
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1
    {
        // Fields
        private bool _allowExecute;

        // Constructors

        public Window1()
        {
            InitializeComponent();
        }

        static Window1()
        {
            MyCommand = new RoutedUICommand("MyCommand", "MyCommand", typeof(Window1));
        }

        // Properties
        
        public static RoutedUICommand MyCommand { get; private set; }

        // Event Handlers

        private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            _allowExecute = !_allowExecute;  
        }

        private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = _allowExecute;
        }

        private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            MessageBox.Show("Command Executed");
        }
    }
}

Comments (8)

Posted 10 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Andy,

We have an optimization in there to not attach to can execute calls if the button is hidden by default. This saves on processing times for command handling when buttons on ribbon are not displayed. Since ribbons can contain hundreds of commands, it speeds things up.

However we do allow you to change this by making your own Button class override like this:
public class MyButton : ActiproSoftware.Windows.Controls.Ribbon.Controls.Button {
    protected override bool CanUpdateCanExecuteWhenHidden {
        get {
            return true;
        }
    }
}
If you use that button instead, it works ok.


Actipro Software Support

Posted 10 years ago by Andy Ver Murlen
Avatar
Thanks!
Posted 10 years ago by Andy Ver Murlen
Avatar
Actually, I have found an issue with this method. I am using the m-v-vm pattern extensively in my application (My forms are bound to my viewmodel classes). Any forms that use the "extended" button are being prevented from being finalized, which in turn prevents my viewmodels from being finalized, because the "unfinalized" form holds a reference to them.

Obviously, setting the CanUpdateCanExecuteWhenHidden property to true is causing something to hold a reference to the form, but I can't figure out what. All I know for sure is it's on your side, because if I change to a normal button or even the standard Actipro ribbon button, the issue goes away.
Posted 10 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Andy,

When that option is set, it will be attaching to the command's CanExecuteChanged handler. Normally this attachment only happens while the control is visible but that option overrides it the visible requirement.

We were looking at the code and may be able to switch the ties to use weak references so that controls don't get retained in memory.

Can you email over a simple sample project that shows the controls being retained in memory with the current codebase so that we can test a code change and ensure it resolves the issue? Thanks!


Actipro Software Support

Posted 10 years ago by Andy Ver Murlen
Avatar
I'll try to. My project is massive, so I'll have to try to build a simple recreation...the key will be figuring out a way to demonstrate it, while keeping it simple :)
Posted 10 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Maybe something simple like the sample code you originally had in this thread but that in a separate window that shows how you see the retention of objects?


Actipro Software Support

Posted 10 years ago by Andy Ver Murlen
Avatar
Just sent it in.
Posted 10 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Thanks for the sample. We changed how we stored event references internally so that this problem has been eliminated. The update will be in build 503.


Actipro Software Support

The latest build of this product (v2019.1 build 0681) was released 1 month ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.