2016-08-15 2 views
0

Ниже приводится очень простой пример Prism.Wpf с DelegateCommand, который имеет как Execute, так и CanExecute делегатов.Призма: необходимо вызвать RaiseCanExecuteChanged() явно

Предположим, что CanExecute зависит от недвижимости. Похоже, что Prism's DelegateCommand не переоценивает условие CanExecute автоматически, когда это свойство изменяется, так как RelayCommand делает в других фреймворках MVVM. Вместо этого вы должны вызвать RaiseCanExecuteChanged() явно в настройщике свойств. Это приводит к множеству повторяющихся кодов в любой нетривиальной viewmodel.

Есть ли лучший способ?

ViewModel:

using System; 
using Prism.Commands; 
using Prism.Mvvm; 

namespace PrismCanExecute.ViewModels 
{ 
public class MainWindowViewModel : BindableBase 
{ 
    private string _title = "Prism Unity Application"; 
    public string Title 
    { 
     get { return _title; } 
     set { SetProperty(ref _title, value); } 
    } 
    private string _name; 
    public string Name 
    { 
     get { return _name; } 
     set 
     { 
      SetProperty(ref _name, value); 

      // Prism doesn't track CanExecute condition changes? 
      // Have to call it explicitly to re-evaluate CanSubmit() 
      // Is there a better way? 
      SubmitCommand.RaiseCanExecuteChanged(); 
     } 
    } 
    public MainWindowViewModel() 
    { 
     SubmitCommand = new DelegateCommand(Submit, CanSubmit); 
    } 

    public DelegateCommand SubmitCommand { get; private set; } 
    private bool CanSubmit() 
    { 
     return (!String.IsNullOrEmpty(Name)); 
    } 
    private void Submit() 
    { 
     System.Windows.MessageBox.Show(Name); 
    } 

} 
} 

Просмотр:

<Window x:Class="PrismCanExecute.Views.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:prism="http://prismlibrary.com/" 
    Title="{Binding Title}" 
    Width="525" 
    Height="350" 
    prism:ViewModelLocator.AutoWireViewModel="True"> 
<Grid> 
    <!--<ContentControl prism:RegionManager.RegionName="ContentRegion" />--> 
    <StackPanel> 
     <StackPanel Orientation="Horizontal"> 
      <TextBlock Text="Name: " /> 
      <TextBox Width="150" 
        Margin="5" 
        Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"/> 
     </StackPanel> 
     <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"> 
      <Button Width="50" 
        Command="{Binding SubmitCommand}" 
        Content="Submit" Margin="10"/> 
      <!--<Button Width="50" 
        Content="Cancel" 
        IsCancel="True" Margin="10"/>--> 
     </StackPanel> 
    </StackPanel> 
</Grid> 
</Window> 

ответ

4

Как объяснил @ l33t, это соизволил. Если вы хотите, чтобы DelegateCommand автоматически отслеживал свойства VM для изменений, просто используйте метод ObservesProperty у делегатаCommand:

var command = new DelegateCommand(Execute).ObservesProperty(()=> Name); 
1

Это дизайн. Это связано с производительностью.

Хотя вы, , можете использовать вместо Призмы DelegateCommand с помощью специальной команды, которая делает то, что вы хотите. Например. this осуществление, похоже, делает трюк. Однако я бы не рекомендовал его использовать. Вероятно, вы столкнетесь с проблемами производительности, если у вас много команд.

Также см. Это answer.

+0

Спасибо. Я также нашел следующие ссылки весьма полезными: (http://stackoverflow.com/questions/33459183/how-to-make-the-canexecute-trigger-properly-using-prism-6?rq=1) и связанные (http : //stackoverflow.com/questions/33313190/observesproperty-method-isnt-observing-models-properties-at-prism-6) – mechanic

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