2013-08-19 11 views
6

Ho una lista di selezione modificabile personalizzata sulla mia finestra wpf. Ho anche una classe ViewModel con cambiato proprietà che sembra che:Come eseguire il binding alla proprietà con accesso solo get

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

Quindi, vorrei legare il mio pulsante Salva per questa proprietà:

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

La mia domanda è come aggiornare Salva pulsante se una delle righe di lista è cambiata?

risposta

2

Il modo corretto per gestire i pulsanti è implementare l'interfaccia ICommand. Ecco un esempio dalla mia soluzione:

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 
} 

È possibile quindi databind a pulsante mi piace questo:

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

ciò che resta è dichiarare una proprietà ICommand sul tuo ViewModel:

public ICommand MyCommand { get; private set; } 

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

Lo stato del pulsante si aggiornerà automaticamente sulla maggior parte delle modifiche. Se per qualche motivo non funziona, puoi forzare l'aggiornamento chiamando lo CommandManager.InvalidateRequerySuggested

1

tuo ViewModel dovrebbe attuare INotifyPropertyChanged e dovrebbe aumentare il PropertyChanged eventi per HasChanges quando mai si cambia un cliente in customers

Aggiornamento:

Se i clienti a implementare INotifyPropertyChanged e clienti è di per sé è una collezione osservabile. È possibile iscriversi e, a seconda dell'azione, annullare la sottoscrizione a tutti i clienti nello CollectionChangedEvent della raccolta customers.

0

Se ViewModel implementa INotifyPropertyChanged, è sufficiente chiamare il metodo OnPropertyChanged() su HasChanges. Con Prism, il metodo equivalente è RaisePropertyChanged.

Tuttavia, con MVVM, è possibile inserire tale test nel metodo CanExecute del comando che è associato alla proprietà Comando del pulsante. Questo gestirà automaticamente IsEnabled.

2

Per consentire a WPF di reagire ai cambiamenti delle proprietà, la classe deve implementare l'interfaccia INotifyPropertyChanged. È necessario inviare le notifiche ogni volta che un cliente viene modificato, come ad esempio:

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

Il pulsante in qualche modo deve ricevere notifiche. Nel tuo caso probabilmente implementerai l'interfaccia INotifyPropertyChanged nel tuo viewmodel. Quando viene modificata la "riga di elenco", è necessario generare l'evento PropertyChanged per la proprietà "HasChanges". Le modifiche dovrebbero essere notate comunque in you viewmodel e lì l'evento dovrebbe essere sollevato. Come soluzione diversa dal momento che si dispone di un viewmodel, è possibile utilizzare un comando sul pulsante e CanExecute restituirà la logica true o false, che deve essere contrassegnata dall'utente al momento della modifica.