Dowemo
0 0 0 0


Question:

I have a button that has a datatrigger that is used to disable the button if a certain property is not set to true:

<Button Name="ExtendButton" Click="ExtendButton_Click"  Margin="0,0,0,8">
    <Button.Style>
        <Style>
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsConnected}" Value="False">
                    <Setter Property="Button.IsEnabled" Value="False" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
</Button.Style>

That's some very simple binding, and it works perfectly. I can set "IsConnected" true and false and true and false and true and false, and I love to see my button just auto-magically become disabled, then enabled, etc. etc.

However, in my Button_Click event... I want to:

  • Disable the button (by using ExtendButton.IsEnabled = false;)
  • Run some asynchronous code (that hits a server... takes about 1 second).
  • Re-enable the button (by using ExtendButton.IsEnabled = true;)
  • The problem is, the very instant that I manually set IsEnabled to either true or false... my XAML binding will never fire again. This makes me very sad :(

    I wish that IsEnabled was tri-state... and that true meant true, false meant false and null meant inherit. But that is not the case, so what do I do?


    Best Answer:


    There's a much better way to get this functionality in WPF. It's the commanding system, and it's awesome. Any button, menu item, hot key, etc can be linked to a single command which automatically handles enabling/disabling (as you desire in your program). It's also clean and reusable, and sooooo easy to use.

    For example, in an application of mine, I have an "about dialog" that shows up when the user hits F1. I created a command called AboutCommand by implementing ICommand.

    public class AboutCommand:System.Windows.Input.ICommand
    {
        public bool CanExecute(object parameter)
        {
            return true; // in this case the command is never disabled
        }
        public event EventHandler CanExecuteChanged
        {
            // not needed in this case, but in commands when CanExecute actually
            // changes, this performs the "magic" of disabling/enabling your controls
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
        public void Execute(object parameter)
        {
            new AboutWindow().ShowDialog(); //happens when the command is executed
        }
    }

    Then, in my window's xaml, I added*:

    <Window.Resources>
        <local:AboutCommand x:Key="About"/>
    </Window.Resources>
    <Window.InputBindings>
        <KeyBinding Command="{StaticResource About}" Gesture="F1"/>
    </Window.InputBindings>

    You could also set the command to a button like so.

    <Button Command="{StaticResource About}" Content="About this program"/>

    Both the F1 key and the button would be disabled if AboutCommand.CanExecute() returned false.

    *(I actually did it differently, because I'm using the MVVM pattern, but this works if you aren't using that pattern.)




    Copyright © 2011 Dowemo All rights reserved.    Creative Commons   AboutUs