XAML.cz Magazín moderních technologií založených na XAML

Silverlight 4 Commands–Enable/Disable Button

Napsáno pro Silverlight od Lukáš Kubis [09.12.2010]
Úvod

V dnešním článku si ukážeme jak svázat tlačítko s Commandem a jak tomuto Commandu přidat nějakou podmínku, za které ho lze spustit či nikoliv. Pokud nebude splněna podmínka, tlačítko bude “disable”, jinak “enable”.

Command

Běžně jste zvyklí, že když někdo klikne na tlačítko, vyvolá se událost Click. V Silverlightu (I ve WPF) pokud nastavíme tlačítku Command, tak po stisku tlačíka se nevyvolá událost Click, ale nýbrž náš Command. “Náš Command” je třída implementující interface ICommand, který nabízí několik metod:

public interface ICommand
{
     bool CanExecute(object parameter);
     void Execute(object parameter);
     event System.EventHandler CanExecuteChanged;
}

Vytvoříme si tedy třídu, implementující zmiňovaný interface. Třída obsahuje pouhé dvě vlastnosti: akci, která se má vykonat a podmínku, za jaké je povoleno tuto akci vykonat.

public class RelayCommand : ICommand
{
    #region Fields

    private readonly Action< object > _execute;
    private readonly Predicate< object > _canExecute;

    #endregion // Fields

    #region Constructors

    public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
    {
        if ( execute == null )
            throw new ArgumentNullException("execute");

        _execute = execute;
        _canExecute = canExecute;
    }

    #endregion // Constructors

    #region ICommand Members

    [DebuggerStepThrough]
    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute(parameter);
    }

    public void Execute(object parameter)
    {
        _execute(parameter);
    }

    #endregion // ICommand Members

    public event EventHandler  CanExecuteChanged;
}

Nyní si už vytvoříme pouze náš ViewModel, ve kterém definujeme náš Command a potřebnou logiku, která bude rozhodovat o tom, zda se může či nemůže command vykonat. ViewModel je velice jednoduchý, máme zde pouze vlastnost FirstName, která když nabyde hodnoty “Test”, tak se tlačítko povolí a my budeme moct provést fiktivní uložení.

public class MainPageViewModel : ViewModelBase
{
    private string _firstName;
    private ICommand _saveCommand;

    public string FirstName
    {
        get { return _firstName; }
        set
        {
            _firstName = value;
            OnPropertyChanged("FirstName");
        }
    }

    public ICommand SaveCommand
    {
        get
        {
            if ( _saveCommand == null )
                _saveCommand = new RelayCommand(param => Save(), condition => IsValid);

            return _saveCommand;
        }
    }

    void Save()
    {
        MessageBox.Show("Saved");
    }

    public bool IsValid
    {
        get
        {
            // vlastnost, ktera vrati true nebo false podle toho zda jsou
            // vyplnene data ve formulari validni
            if ( string.IsNullOrEmpty(FirstName) )
                return false;

            return FirstName == "Test";
        }
    }
}

Ještě než spustíme aplikace, tak Vám zde ukážu implementaci třídy ViewModelBase a MainPage.xaml.

ViewModelBase

public abstract class ViewModelBase : INotifyPropertyChanged, IDisposable
{
    #region | Constructor

    protected ViewModelBase()
    {
    }

    #endregion // Constructor

    #region INotifyPropertyChanged Members
       
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = this.PropertyChanged;
        if ( handler != null )
        {
            var args = new PropertyChangedEventArgs(propertyName);
            handler(this, args);
        }
    }

    #endregion // INotifyPropertyChanged Members

    #region IDisposable Members

    public void Dispose()
    {
        this.OnDispose();
    }

    protected virtual void OnDispose()
    {
    }

    #endregion // IDisposable Members
}

MainPage.xaml

<StackPanel x:Name="LayoutRoot" Background="White">
    <TextBox Text="{Binding FirstName, Mode=TwoWay}"/>
    <Button Content="Save" Command="{Binding SaveCommand}"/>
</StackPanel>

MainPage.xaml.cs

public MainPage()
{
    InitializeComponent();

    this.DataContext = new MainPageViewModel();
}

Nyní když aplikaci spustíte, napíšete do textového pole Test a stisknete Tab (aby textbox ztratil focus), tak uvidíte, že se nic nestane a tlačítko zůstane zakázané (nelze na něho kliknout). Co je špatně?

Auto Enable/Disable Button

Aby jsme povolili automatické povolení tlačítka, v případě platné podmínky, je potřeba ve vhodný okamžik vyvolat událost CanExecuteChanged, která ověří naší podmínku a v případě, že je podmínka validní, se tlačítko povolí.Pro srovnání WPF obsahuje třídu CommandManager, která I když uživatel pouze přejíždí myší po UI, tak automaticky vyvolává tuto událost, Silverlight nikoliv!.

Provedeme menší úpravy v našem kódu:

Vytvoříme nový interface nazvaný IRelayCommand

public interface IRelayCommand : ICommand
{
    void RaiseCanExecuteChanged();
}

Zaměníme class RelayCommand : ICommand za class RelayCommand : IRelayCommand a v MainPageViewModel bude SaveCommand typu IRelayCommand.

Na závěr už jenom upravíme setter vlastnosti FirstName, že po volání OnPropertyChanged(“FirstName”) zavoláme

SaveCommand.RaiseCanExecuteChanged();

čímž se provede otestování vlastnosti IsValid, která v případě, že FirstName obsahuje slovo Test vrátí True a tlačítko bude povolené.

Materiály ke stažení

Demo

Komentáře

ukládám komentář, vyčkejte prosím..
  1. Buďte první, kdo napíše komentář.

@xamlcz

  • RT @jvanrhyn: XAML, It's a bit like olives. Takes a while to get used to. But once you're used to it. It is actually pretty good. <3 XAML
  • RT @moser_christian: WPF Inspector 0.9.7 is released. It supports .NET 3.5 and 4.0 The project is now open source and available on CodeP ...
  • Jeff Handley oznámil vydání WCF RIA Services v.1.0 SP1 RTM http://bit.ly/gOgckn ke stažení na http://bit.ly/gVAXdK
  • jedna výzva pro Brno. Byl někdo z vás na přednášce o RIA v MS Akvárku? Dejte o sobě vědět. Děkuji
  • také jste uvažovali o tom, že zkusíte na projekt použít Caliburn Micro nebo naopak Prism 4? A co tak obojí, šlo by to nebo ne? Již brzy