Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在avalonia中的属性激活时使用_C#_Reactiveui_Avaloniaui_Avalonia - Fatal编程技术网

C# 如何在avalonia中的属性激活时使用

C# 如何在avalonia中的属性激活时使用,c#,reactiveui,avaloniaui,avalonia,C#,Reactiveui,Avaloniaui,Avalonia,我正在尝试与Avalonia一起使用ReactiveUI。由于Avalonia 0.10预览中的初始化顺序,以下代码失败: class ViewModel : IActivatableViewModel { public ViewModel(){ this.WhenActivated(disposables => { _myProperty = observable.ToProperty(this, nameof(MyProperty)).D

我正在尝试与Avalonia一起使用ReactiveUI。由于Avalonia 0.10预览中的初始化顺序,以下代码失败:

class ViewModel : IActivatableViewModel
{
    public ViewModel(){
        this.WhenActivated(disposables => {
            _myProperty = observable.ToProperty(this, nameof(MyProperty)).DisposeWith(disposables).
        });
    }

    private ObservableAsPropertyHelper<object> _myProperty = null!;
    public object MyProperty => _myProperty.Value;
}
class-ViewModel:IActivatableViewModel
{
公共视图模型(){
此。当激活时(一次性=>{
_myProperty=observable.ToProperty(此名称为(myProperty)).DisposeWith(可处置)。
});
}
私有ObservablesPropertyHelper_myProperty=null!;
公共对象MyProperty=>\u MyProperty.Value;
}
因为在视图绑定到viewModel之后调用了WhenActivated(因此_myProperty为null)

我认为没有简单的解决方法需要大量的黑客,手动提高属性等等

因此,问题是:

如何与OAPH合作以及何时在Avalonia开展活动?

选项#1

允许您解决此问题的最明显模式是使用null合并运算符。通过使用此运算符,您可以通过调整代码使其看起来有点像这样来实现所需的行为:

private ObservablesPropertyHelper_我的财产;
公共TValue MyProperty=>\u MyProperty?.Value;
在这里,我们使用新的C#nullable注释将声明的字段显式标记为可空。我们这样做是因为在调用
WhenActivated
块之前,
\u myProperty
字段设置为
null
。此外,我们在这里使用
\u myProperty?.Value
语法,因为当视图模型未初始化时,
myProperty
getter应该返回
null

选项2

肯定更好的另一个选项是在激活时将
TopProperty
订阅移到
块之外,并将
ObservablesPropertyHelper
字段标记为
只读
。如果您的计算属性未订阅比视图模型更有效的外部服务,则无需处理由
TopProperty
返回的订阅。在90%的情况下,当启动时,您不需要将
ToProperty
调用保留在
中。有关更多信息,请参阅文档页面。另请参阅这篇文章,这篇文章也可以为这个主题提供一些启示。因此,在90%的情况下,编写这样的代码是一种很好的方法:

private readonly ObservableAsPropertyHelper\u myProperty;
公共TValue MyProperty=>\u MyProperty.Value;
//在视图模型构造函数中:
_myProperty=obs.ToProperty(这个,x=>x.myProperty);
如果您实际订阅外部服务,例如通过构造函数注入视图模型,则可以使用私有setter将
MyProperty
转换为读写属性,并编写以下代码:

class-ViewModel:IActivatableViewModel
{
公共视图模型(IDependency依赖)
{
此。当激活时(一次性=>
{
//我们现在使用的是“DisposeWith”
//订阅一个外部依赖项
//可能比视图模型更长寿。所以
//我们需要按顺序处理订阅
//以避免内存泄漏的可能性。
附属国
.外部可观察
.Subscribe(value=>MyProperty=value)
.一次性使用(一次性使用);
});
}
私人TValue_myProperty;
公共TValue MyProperty
{
get=>\u myProperty;
private set=>this.RaiseAndSetIfChanged(ref\u myProperty,value);
}
}
另外,看看
RaiseAndSetIfChanged
语法是否让您觉得太冗长

选项#3(我推荐这个选项)

值得注意的是,Avalonia支持。这是一个非常有用的功能,我强烈建议您尝试一下。这意味着,在Avalonia中,您可以简单地将计算属性声明为
IObservable
,Avalonia将为您管理订阅的生存期。因此,在视图模型中,请执行以下操作:

class-ViewModel:IActivatableViewModel
{
公共视图模型()
{
我的财产=
此.whenyValue(x=>x.AnotherProperty)
.Select(value=>$“您好,{value}!”);
}
公共IObservable MyProperty{get;}
//为简洁起见省略了几行
}
在视图中,编写以下代码:


OAPHs是为无法实现这些技巧的平台而发明的,但Avalonia非常擅长巧妙的标记扩展。因此,如果您针对多个UI框架并编写与框架无关的视图模型,那么OAPH是一个不错的选择。但是如果您只针对Avalonia,那么只需使用
{Binding^}

选项4

或者,如果您愿意使用,请将选项3中的视图模型代码与
xaml.cs
文件中视图侧的以下代码组合在一起:

this.WhenActivated(cleanup=>{
此.whenObservable(x=>x.ViewModel.MyProperty)
.BindTo(这个,x=>x.NamedTextBox.Text)
.处置(清理);
});
这里我们假设
xaml
文件如下所示:



我们现在有了一个可能有助于生成
x:Name
references顺便说一句。

感谢您的详细回答!选项1很糟糕,完全违背了做有趣事情的目的。选项2有点没用,因为它都是关于外部依赖的。选项#3很棒,但为什么我必须使用
^
?看起来很奇怪,^符号只是一种Avalonia标记扩展语法,允许将控件绑定到任务和可观察对象。它允许我们告诉Avalonia,我们绑定到的值是一个
任务
IObservable
,绑定应该有不同的行为,并跟踪他们称之为“流绑定操作符”的订阅,但这难道不是默认行为吗?如果观察到某事