O programa de configuração
Vamos supor o seguinte. Temos o seguinte teórico classe viewmodel para aplicação de 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)
}
Além disso:
- Atual classe implementa corretamente
INotifyPropertyChanged
- Todas as classes no acesso ao portal cadeias implementa corretamente
INotifyPropertyChanged
(por exemplo. documento viewmodel acessível a partir deActiveDocument
propriedade) ActiveDocument
pode sernull
.ActiveDocument.Highlighting
também pode ser nulo.
O problema
Eu gostaria que o comando seja ativado apenas quando a condição comentário é atendida.
Opção sem RX
Eu escrevi a minha própria biblioteca para manipulação de tais situações. A solução seria:
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)
}
Ou - se você quer que o código a ser um pouco mais legível, para que parcial, as condições poderiam ser reutilizados, como:
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)
}
O que a minha biblioteca (ou, mais precisamente, LambdaCondition
classe) faz é:
- Ele mantém o controle de todas as instâncias de execução
INotifyPropertyChanged
e lidar com mudanças (por exemplo. quandoActiveDocument
alterações ouActiveDocument.Highlighting
alterações ouActiveDocument.Highlighting.Type
alterações etc.) - Ele mantém o controle de possíveis
null
s no caminho, caso em que será retornar ao valor padrão (neste caso,false
) - Ele será automaticamente relatórios de alterações (mas apenas alterações) de disponibilidade para o comando, de modo que a INTERFACE do usuário pode ser atualizada quando necessário.
A pergunta
Como seria de se implementar o cenário descrito acima, usando o System.Reactive
em C#? É possível fazê-lo facilmente, mantendo todos os requisitos de cerca de INotifyPropertyChanged
, nulos sobre a forma e o valor padrão? Você pode fazer qualquer sã pressupostos, quando necessário.