El programa de instalación
Supongamos el siguiente. Tenemos una siguiente teórica clase viewmodel para la aplicación 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)
}
Además:
- Actual clase implementa correctamente
INotifyPropertyChanged
- Todas las clases de acceso de los miembros de las cadenas implementa correctamente
INotifyPropertyChanged
(por ejemplo. documento viewmodel accesible desdeActiveDocument
de la propiedad) ActiveDocument
puede sernull
.ActiveDocument.Highlighting
también puede ser null.
El problema
Me gustaría que el comando se activa sólo cuando la condición en el comentario se cumple.
Opción sin RX
Escribí mi propia biblioteca para el manejo de tales situaciones. La solución sería:
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)
}
O - si desea que el código sea un poco más fácil de leer, así que parcial de las condiciones podrían ser reutilizados, como que:
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)
}
Lo que mi biblioteca (o, más precisamente, LambdaCondition
clase) es:
- Mantiene un registro de todas las instancias de la aplicación
INotifyPropertyChanged
y manejar los cambios (por ejemplo. cuandoActiveDocument
los cambios oActiveDocument.Highlighting
los cambios oActiveDocument.Highlighting.Type
cambios etc.) - Realiza un seguimiento de los posibles
null
s en el camino, en cuyo caso se devolverá el valor por defecto (en este caso,false
) - Se le informa automáticamente de los cambios (pero sólo a los cambios) de la disponibilidad para el comando, por lo que la interfaz de usuario puede ser actualizada cuando sea necesario.
La pregunta
La manera de implementar el escenario descrito anteriormente, utilizando System.Reactive
en C#? Es posible hacerlo fácilmente, manteniendo todos los requisitos sobre INotifyPropertyChanged
, los valores nulos en el camino, y el valor predeterminado? Usted puede hacer cualquier cuerdo supuestos cuando sea necesario.