Do czego może służyć tak naprawdę interfejs ICommand?

0

Witajcie. Przejrzałem wiele przykładów co do działania interfejsu ICommand, o dziwo wszystko działa. Tylko patrząc na przykład:

<Button Name="button" Content="Dodaj" Command="{Binding Command1}" CommandParameter="Add" Height="30"/>

to tak naprawdę nie rozumiem do czego odnosi się to. W którym momencie jest sprawdzane CanExecute(), jaki ma wpływ CommandParameter na wykonywanie komendy i w których momentach i jak to się w ogóle dzieje. Podajcie mi proszę jakiś przykład zastosowania komend w dużych aplikacjach abym mógł to choć troszkę zrozumieć. Byłbym wdzięczny

2

W którym momencie jest sprawdzane CanExecute()?

To jest sprawdzane cały czas w pętli działania programu.

Jaki ma wpływ CommandParameter na wykonywanie komendy i w których momentach i jak to się w ogóle dzieje?

Nie ma żadnego wpływu. Albo przesyłasz do komendy parametr albo nie. Od Ciebie zależy co z tym robisz. Możesz go przekazać i nawet nie obsłużyć wewnątrz viewmodelu. Jeżeli prześlesz coś parametrem to automatycznie w metodach bool CanExecute(object parameter) i void Execute(object parameter) argument metody będzie nienullowy. Przekazywanie przez parametr różnych rzeczy jest przydatne w przypadku kiedy nie można zbindować czegoś do własności np. kontrolki PasswordBox. W tym przypadku najlepiej użyć parametru.

Podajcie mi proszę jakiś przykład zastosowania komend w dużych aplikacjach abym mógł to choć troszkę zrozumieć.

Komendy w dużych aplikacjach działają tak samo jak w małych. Nie ma tutaj specjalnej filozofii. Trzeba natomiast uważać ze sprawdzaniem CanExecute. Jako, że sprawdzane jest to bez przerwy w pętli działania programu to potrafi czasami zwolnić apkę jeżeli jest źle napisane np:

        public ICommand OdSth
        {
            get
            {
                return new RelayCommand(() =>
                {
                 // Some code...
                } ,()=> this.Check() /*  CanExecute checking... */ );
            }
        }

Jeżeli private bool Check() iteruje po jakiejś strasznie dużej kolekcji, a jak wiadomo sprawdzane jest to bez przerwy w pętli programu to wiadomo, że zwolni Ci to aplikację. Wtedy wywołanie takiej metody należałoby jakoś zwarunkować, żeby sprawdzanie odbywało się powiedzmy tylko raz, w zależności od czegoś tam ważnego i jeśli to coś ważnego się zmieni to sprawdź kolejny raz.

No i oczywiście bardzo ważna sprawa: długie komendy to złe komendy. Tak samo komendy, które realizują logikę biznesową, która to powinna być realizowana przez klasy serwisowe modelu. Komendy w VM mają po prostu wykonywać metody modelu i wtedy jest to najbardziej czytelne.

0

No dobrze. Według przykładu co podałem wyżej mam przycisk dodawania. Jak napisano w przykładzie w zależności jak obsłużę CanExecute mogę zdeaktywować przycisk dodawania, gdy załóżmy textbox jest pusty. To akurat rozumiem, ale nie rozumiem czemu po kliknięciu w przycisk uruchamia mi sie Execute, a nie np. po najechaniu na przycisk, czy też jakiekolwiek inne zdarzenie? Czy da się to jakoś ustawić?

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            this.DataContext = this;
            this.Command1 = new cCommand(ExecuteCommand1, CanExecuteCommand1);
            InitializeComponent();
        }
        public ICommand Command1 { get; protected set; }
        public bool CanExecuteCommand1(object parameter)
        {
            return true;
        }
        public void ExecuteCommand1(object parameter)
        {
            MessageBox.Show("Executing command 1");
        }

    }

    public class cCommand : ICommand
    {
        public delegate void ICommandOnExecute(object parameter);
        public delegate bool ICommandOnCanExecute(object parameter);

        private ICommandOnExecute _execute;
        private ICommandOnCanExecute _canExecute;

        public cCommand(ICommandOnExecute onExecuteMethod, ICommandOnCanExecute onCanExecuteMethod)
        {
            _execute = onExecuteMethod;
            _canExecute = onCanExecuteMethod;
        }

        #region ICommand Members

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public bool CanExecute(object parameter)
        {
            return _canExecute.Invoke(parameter);
        }

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

        #endregion
    }
2

Command wywoływany jest po naciśnięciu ponieważ tak to zostało napisane. Odsyłam do dokumentacji https://msdn.microsoft.com/pl-pl/library/system.windows.controls.button(v=vs.110).aspx
Tak możesz przypisać Commandy do innych zdarzeń. Poszukaj na google czegoś w stylu "wpf event to command interactivity" jest tego dużo.
Tak ogólnie to jest od tego biblioteka System.Windows.Interactivity, i w definicji kontrolki łączysz określony event z commandem

1

Albo napisać własne AttachedBehaviour, które zmapuje jakiego chcesz eventa na komendę.

0

Teraz juz rozumiem, dzięki! Biorę się do roboty. Jak gdzies utknę będę pisać ! Miłego dnia wszystkim życzę :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1