2013-08-19 10 views
6

Mam niektóre niestandardowe edytowalne pole listy w moim oknie wpf. Mam także klasę ViewModel z nieruchomości Zmieniono który wygląda tak:Jak powiązać z usługą tylko uzyskać akcesor

public bool HasChanges 
{ 
    get 
    { 
     return customers.Any(customer => customer.Changed); 
    } 
} 

Więc chciałbym związać mój przycisk Zapisz, aby ten obiekt:

<Button IsEnabled="{Binding HasChanges, Mode=OneWay}"... 

moje pytanie jest jak zaktualizować Zapisz przycisk, jeśli jeden z wierszy listbox zostanie zmieniony?

Odpowiedz

2

Właściwym sposobem postępowania z przyciskami jest implementacja interfejsu ICommand. Oto przykład z mojego rozwiązania:

public class RelayCommand : ICommand 
{ 
    readonly Action<object> _execute; 
    readonly Predicate<object> _canExecute; 

    public RelayCommand(Action<object> execute) : this(execute, null) 
    { 
    } 

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

     _execute = execute; 
     _canExecute = canExecute;   
    } 

    #region ICommand Members 

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

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

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

    #endregion 
} 

Można wtedy DataBind do przycisku tak:

<Button Command="{Binding MyCommand}" .../> 

Co lewa jest zadeklarować właściwość ICommand na viewmodel:

public ICommand MyCommand { get; private set; } 

//in constructor: 
MyCommand = new RelayCommand(_ => SomeActionOnButtonClick(), _ => HasChanges); 

Stan przycisku zostanie automatycznie zaktualizowany po większości zmian. Jeśli nie z jakiegoś powodu - możesz wymusić aktualizację, dzwoniąc pod numer CommandManager.InvalidateRequerySuggested

1

Twój ViewModel powinny wdrożyć INotifyPropertyChanged i powinna podnieść PropertyChanged wydarzenie dla HasChanges gdy kiedykolwiek zmienić klienta w customers

Aktualizacja:

Jeśli klienci wdrożyć INotifyPropertyChanged i klientów to samo jest obserwowalne kolekcja. Możesz subskrybować, a także w zależności od akcji rezygnacji, wszystkich klientów z kolekcji CollectionChangedEvent z Twojej kolekcji .

0

Jeśli Twój ViewModel implementuje INotifyPropertyChanged, wystarczy wywołać metodę OnPropertyChanged() na HasChanges. W przypadku Prism równoważną metodą jest RaisePropertyChanged.

Jednakże, z MVVM, możesz chcieć umieścić ten test w metodzie CanExecute twojego polecenia, która jest związana z właściwością Command przycisku. Spowoduje to automatyczne obsłużenie IsEnabled.

2

Aby WPF reagował na zmiany właściwości, klasa musi implementować interfejs INotifyPropertyChanged. Musisz wysyłać powiadomienia za każdym razem, gdy zmienia się klienta, na przykład:

class CustomerList : INotifyPropertyChanged { 
    public event PropertyChangedEventHandler PropertyChanged; 
    private List<Customer> customers = ... 
    public bool HasChanges { 
     get { 
      return customers.Any(customer => customer.Changed); 
     } 
    } 
    // Callers who change customers inside your list must call this method 
    public void ChangeCustomer(Customer c) { 
     // Do whatever you need to do, ... 
     ... 
     // then send out the notification to WPF 
     OnPropertyChanged("HasChanges"); 
    } 
    protected void OnPropertyChanged(string name) { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) { 
      handler(this, new PropertyChangedEventArgs(name)); 
     } 
    } 
} 
0

Przycisk musi jakoś odbierać powiadomienia. W twoim przypadku prawdopodobnie implementujesz interfejs INotifyPropertyChanged w swoim viewmodelu. Kiedy twój "wiersz listbox zostanie zmieniony" powinieneś podnieść zdarzenie PropertyChanged dla właściwości "HasChanges". Zmiany należy jednak zauważyć w tobie viewmodel i tam wydarzenie powinno zostać podniesione. Jako inne rozwiązanie, ponieważ dysponujesz modelem podglądu, możesz użyć polecenia na przycisku, a CanExecute będzie logicznie zwracać wartość true lub false, która również musi zostać oznaczona przez ciebie, gdy nastąpią zmiany.

Powiązane problemy