如何使用RX控制的命令就是提供在复杂的情况?

0

的问题

设置

让我们假设以下。 我们有一个下面的 理论 模型类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 (eg. 文档模型可以从 ActiveDocument 酒店)
  • ActiveDocumentnull. 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 class)是:

  • 它跟踪所有实例执行 INotifyPropertyChanged 以及处理变化(例如。 时 ActiveDocument 变化或者 ActiveDocument.Highlighting 变化或者 ActiveDocument.Highlighting.Type 变化等。)
  • 它跟踪的可能 nulls在的方式在这种情况下,它将返回的默认值(在这种情况下, false)
  • 它会自动报告的修改(但只有改变)性的命令,以便UI可以刷新,需要的时候。

这个问题

如何能实现上述情况使用 System.Reactive 在C#? 这是能够做到这一点很容易,同时保持所有有关要求 INotifyPropertyChanged,null的方式和默认的价值? 你可以做任何理智的假设需要的时候。

c# mvvm system.reactive wpf
2021-11-23 15:15:48
1

最好的答案

0

ReactiveUI 框架有一个 ReactiveCommand 类使用的一个 IObservable<T> 刷新的状态的命令(即提高 CanExecuteChanged 事件的 ICommand).

请参阅 文件 的示例,如何用它来控制executability:

var canExecute = this.WhenAnyValue(
    x => x.UserName, x => x.Password,
    (userName, password) => 
        !string.IsNullOrEmpty(userName) && 
        !string.IsNullOrEmpty(password));

var command = ReactiveCommand.CreateFromTask(LogOnAsync, canExecute);
2021-11-24 14:52:33

它是否遵循INotifyPropertyChange实施者在酒店接链? 它还能正常工作,如果任何的性质是空? 你能请示,我的特定例子看起来时实现RX?
Spook

WhenAnyValue 并发射一个新的价值时,任何的 UsernamePassword 性rasises的 PropertyChanged 事件。 什么是您的具体例子到底是什么? 什么,你试试吗?
mm8

你有没有读我的整个问题吗? 我已经呈现的确切情况,这是应该被看: vm => m.ActiveDocument.Highlighting.Type == Highlighting.Xml && !vm.ActiveDocument.IsReadOnly && (vm.License.Kind == LicenseKind.Full || vm.License.TrialDay < 30), 什么如果,例如。 ActiveDocument 是空的? 将RX处理这正常吗? 我希望在这种情况下的状况有其默认值(或至少false by default)
Spook

如果 ActiveDocument你会得到一个 NullReferenceException. 这有什么用RX。
mm8

在我的图书馆我不会。 这就是,除其他外,是为什么我感兴趣,无论是RX是非常适合这个任务。
Spook

其他语言

此页面有其他语言版本

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................