2015-11-01 2 views
1

У меня есть модельКак сделать триггер CanExecute правильно с помощью Prism 6

public class Irritant : BindableBase 
{ 
    private short _id; 
    private string _name; 
    private string _description; 

    public short Id 
    { 
     get { return _id; } 
     set { SetProperty(ref _id, value); } 
    } 

    public string Name 
    { 
     get { return _name; } 
     set { SetProperty(ref _name, value); } 
    } 

    public string Description 
    { 
     get { return _description; } 
     set { SetProperty(ref _description, value); } 
    } 


    public Irritant() 
    { 
     Id = 0; 
     Name = ""; 
     Description = "";  
    } 
} 

Тогда мой ViewModel с двумя версиями

public class IrritantViewModel : BindableBase 
{ 
    private IrritantDb db = new IrritantDb(); 


    //Version 1 - The Model's property is coded in IrritantViewModel 
    //private short _id; 
    //private string _name = "Alen"; 
    //private string _description; 

    //public short Id 
    //{ 
    // get { return _id; } 
    // set { SetProperty(ref _id, value); } 
    //} 

    //public string Name 
    //{ 
    // get { return _name; } 
    // set { SetProperty(ref _name, value); } 
    //} 

    //public string Description 
    //{ 
    // get { return _description; } 
    // set { SetProperty(ref _description, value); } 
    //} 


    //Version2 - I use the Irritant Model as property of IrritantViewModel 
    private DateTime? _lastUpdated; 
    private Irritant _entity; 

    public Irritant Entity 
    { 
     get { return _entity; } 
     set { SetProperty(ref _entity, value); } 
    } 

    public DateTime? LastUpdated 
    { 
     get { return _lastUpdated; } 
     set { SetProperty(ref _lastUpdated, value); } 
    } 

    public DelegateCommand UpdateCommand { get; set; } 

    public IrritantViewModel() 
    { 
     Entity = new Irritant(); 

     //Version1 
     //UpdateCommand = new DelegateCommand(EditCommand, CanExecute).ObservesProperty(() => Name); 

     //Version2 
     UpdateCommand = new DelegateCommand(EditCommand, CanExecute).ObservesProperty(() => Entity.Name); 
    } 

    private bool CanExecute() 
    { 
     //Version1 
     //switch (Name) 
     //{ 
     // case null: 
     //  return false; 
     // case "": 
     //  return false; 
     //} 


     //Version2 
     switch (Entity.Name) 
     { 
      case null: 
       return false; 
      case "": 
       return false; 
     } 

     return true; 
    } 

    private void EditCommand() 
    { 
     LastUpdated = DateTime.UtcNow; 
    } 
} 

И это мой взгляд

public partial class IrritantView : UserControl 
{ 
    public IrritantView() 
    { 
     InitializeComponent(); 
     DataContext = new IrritantViewModel(); 
    } 
} 

<Grid > 
    <ScrollViewer> 
     <StackPanel MinWidth="200"> 

     <TextBlock Text="Irritant" /> 



     <!--Version 1--> 
       <!--<TextBlock Text="Name" /> 
       <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" /> 
       <TextBlock Text="Description" /> 
       <TextBox Text="{Binding Description, UpdateSourceTrigger=PropertyChanged}" /> 
       --> 


     <!--Version 2--> 

      <TextBlock Text="Name" /> 
      <TextBox Text="{Binding Entity.Name, UpdateSourceTrigger=PropertyChanged}" /> 
      <TextBlock Text="Description" /> 
      <TextBox Text="{Binding Entity.Description, UpdateSourceTrigger=PropertyChanged}" /> 



      <TextBlock Text="Last Updated" /> 
      <Label Content="{Binding LastUpdated, UpdateSourceTrigger=PropertyChanged}" /> 
      <Button Content="Save" 
        Command="{Binding UpdateCommand}" 
        /> 
     </StackPanel> 
    </ScrollViewer> 
</Grid> 

Версия 1 работает нормально, кнопка «Сохранить» отключается, когда TextBox, привязанный к имени (TextBox Text = «{Binding Name, UpdateSourceTrigger = Pro pertyChanged} ") является нулевым или пустым.

Но с версией 2 кнопка «Сохранить» не отключается. Он вызывает только метод CanExecute во время инициализации, удаление текста в TextBox не отключает Button. Что я сделал не так?

+0

DelegateCommand.ObservesPropery не поддерживает сложные свойства объекта. Он поддерживает только свойства, существующие в ViewModel в команде. Это связано с тем, что жизненный цикл сложных объектов неизвестен, и утечка памяти будет создана, если было создано много экземпляров объекта. Поэтому рекомендуется использовать версию 1 – user1672994

+0

Если я делаю версию 1, то это будет просто VVM вместо MVVM? –

ответ

3

DelegateCommand не возбуждает событие CanExecuteChanged, вам необходимо поднять это событие вручную, позвонив по телефону RaiseCanExecuteChanged, если это необходимо. Помимо использования DelegateCommand, вы можете использовать RelayCommand, который ретранслирует на CommandManager.RequerySuggested событие, которое делает аналогичную вещь для вас.

  1. Измените ваше определение команды возвращения ICommand:

    public ICommand UpdateCommand { get; set; } 
    
  2. Инициализировать команду, используя ниже:

    UpdateCommand = new AutoCanExecuteCommand(new DelegateCommand(EditCommand, CanExecute)); 
    
  3. Используйте следующий класс в качестве оболочки:

    public class AutoCanExecuteCommand : ICommand 
    { 
        public ICommand WrappedCommand { get; private set; } 
    
        public AutoCanExecuteCommand(ICommand wrappedCommand) 
        { 
         if (wrappedCommand == null) 
         { 
          throw new ArgumentNullException("wrappedCommand"); 
         } 
    
         WrappedCommand = wrappedCommand; 
        } 
    
        public void Execute(object parameter) 
        { 
         WrappedCommand.Execute(parameter); 
        } 
    
        public bool CanExecute(object parameter) 
        { 
         return WrappedCommand.CanExecute(parameter); 
        } 
    
        public event EventHandler CanExecuteChanged 
        { 
         add { CommandManager.RequerySuggested += value; } 
         remove { CommandManager.RequerySuggested -= value; } 
        } 
    } 
    
1

Я бы не рекомендовал подключаться к CommandManager по ряду причин. Помимо утечек памяти, это может привести к проблемам с производительностью в ваших приложениях, поскольку у вас нет контроля над тем, когда или сколько раз CommandManager будет вызывать CanExecute (что происходит в потоке пользовательского интерфейса). Вместо этого, я бы рекомендовал использовать INPC вашей модели объекта, а не как показано в этом ответе:

ObservesProperty method isn't observing model's properties at Prism 6

Смежные вопросы