Настройка
Давайте предположим следующее. У нас есть следующий теоретический класс viewmodel для приложения WPF:
public MyViewModel
{
public MyViewModel()
{
// Condition under which this command may be executed is:
// this.ActiveDocument.Highlighting.Type == Highlighting.Xml &&
// !this.ActiveDocument.IsReadOnly &&
// (this.License.Kind == LicenseKind.Full || this.License.TrialDay < 30)
MyCommand = new Command(obj => DoSomething());
}
public ICommand MyCommand { get; }
// (all other required properties)
}
В дополнение:
- Текущий класс реализует правильно
INotifyPropertyChanged
- Все классы в цепочках доступа участников реализуются должным образом
INotifyPropertyChanged
(например, модель представления документа, доступная изActiveDocument
собственность) ActiveDocument
может бытьnull
.ActiveDocument.Highlighting
также может быть нулевым.
Проблема
Я бы хотел, чтобы команда была включена только при выполнении условия в комментарии.
Опция без RX
Я написал свою собственную библиотеку для обработки таких ситуаций. Решением было бы либо:
public MyViewModel
{
private readonly Condition commandAvailableCondition;
public MyViewModel()
{
commandAvailableCondition = new LambdaCondition(this,
vm => m.ActiveDocument.Highlighting.Type == Highlighting.Xml &&
!vm.ActiveDocument.IsReadOnly &&
(vm.License.Kind == LicenseKind.Full || vm.License.TrialDay < 30),
false);
MyCommand = new AppCommand(obj => DoSomething(), commandAvailableCondition);
}
public ICommand MyCommand { get; }
// (all other required properties)
}
Или - если вы хотите, чтобы код был немного более читабельным, чтобы частичные условия можно было использовать повторно - вот так:
public MyViewModel
{
private readonly Condition commandAvailableCondition;
public MyViewModel()
{
var highlightingIsXml = new LambdaCondition(this,
vm => vm.ActiveDocument.Highlighting.Type == Highlighting.Xml,
false);
var documentIsReadonly = new LambdaCondition(this,
vm => vm.ActiveDocument.IsReadOnly,
false);
var appIsLicensed = new LambdaCondition(this,
vm => vm.License.Kind == LicenseKind.Full || this.License.TrialDay < 30,
false);
commandAvailableCondition = highlightingIsXml & !documentIsReadonly & appIsLicensed;
MyCommand = new AppCommand(obj => DoSomething(), commandAvailableCondition);
}
public ICommand MyCommand { get; }
// (all other required properties)
}
Что моя библиотека (или, точнее, LambdaCondition
класс) делает это:
- Он отслеживает все экземпляры, реализующие
INotifyPropertyChanged
и обрабатывать изменения (например. когдаActiveDocument
изменения илиActiveDocument.Highlighting
изменения илиActiveDocument.Highlighting.Type
изменения и т.д.) - Он отслеживает возможные
null
s в пути, и в этом случае он вернет значение по умолчанию (в данном случае,false
) - Он автоматически сообщит команде об изменениях (но только об изменениях) доступности, чтобы при необходимости можно было обновить пользовательский интерфейс.
Вопрос
Как можно было бы реализовать сценарий, описанный выше, используя System.Reactive
в C#? Можно ли это сделать легко, соблюдая все требования к INotifyPropertyChanged
, нули по пути и значение по умолчанию? Вы можете делать любые разумные предположения, когда это необходимо.