C# observeproperty方法是';t观测模型&x27;棱镜6的s性质
我正在尝试学习Prism MVVM,我正在创建一个包含两个字段和一个按钮的窗口,当这两个字段不为空时,该窗口将被启用 问题是我找不到方法使方法C# observeproperty方法是';t观测模型&x27;棱镜6的s性质,c#,wpf,mvvm,prism,C#,Wpf,Mvvm,Prism,我正在尝试学习Prism MVVM,我正在创建一个包含两个字段和一个按钮的窗口,当这两个字段不为空时,该窗口将被启用 问题是我找不到方法使方法observeproperty()在对象上工作(Pessoa)。CanExecuteAtualizar()方法仅在应用程序启动时调用,当我编辑文本字段Nome或SobreName时,按钮不会发生任何变化,并且不会触发该方法 我尝试在没有模型的情况下工作,将Nome、Sobrenome和ultimatualizao属性直接放在ViewModel中,效果很好,
observeproperty()
在对象上工作(Pessoa
)。CanExecuteAtualizar()
方法仅在应用程序启动时调用,当我编辑文本字段Nome
或SobreName
时,按钮不会发生任何变化,并且不会触发该方法
我尝试在没有模型的情况下工作,将Nome
、Sobrenome
和ultimatualizao
属性直接放在ViewModel中,效果很好,根据方法CanExecuteAtualizar
的返回禁用按钮,但我想将其用于模型。有办法做到这一点吗
ViewAViewModel.cs
公共类ViewAViewModel:BindableBase
{
私人佩索阿(Pessoa);;
公共佩索阿佩索阿
{
获取{return\u pessoa;}
set{SetProperty(ref_pessoa,value);}
}
公共ICommand CommandAtualizar{get;set;}
公共视图视图模型()
{
Pessoa=新的Pessoa();
Pessoa.Nome=“加布里埃尔”;
CommandAtualizar=newdelegateCommand(executeatalizar,canexecuteatalizar).observeproperty(()=>Pessoa.Nome).observeproperty(()=>Pessoa.Sobrenome);
}
公共图书馆CanExecuteAtualizar()
{
return!string.IsNullOrWhiteSpace(Pessoa.Nome)和&!string.IsNullOrWhiteSpace(Pessoa.Sobrenome);
}
public void ExecuteAtualizar()
{
Pessoa.ultimatualizao=DateTime.Now;
}
}
Pessoa.cs
公共类Pessoa:BindableBase
{
私有字符串_nome;
公共字符串名称
{
获取{return\u nome;}
集合{SetProperty(ref _nome,value);}
}
私有字符串_sobrenome;
公共字符串Sobrenome
{
获取{return\u sobrenome;}
集合{SetProperty(ref _sobrenome,value);}
}
私人约会时间;
公共日期时间?Ultimatualizao
{
获取{return\u ultimatualizao;}
集合{SetProperty(ref_ultimatualizao,value);}
}
}
ViewA.xaml
DelegateCommand.ObserveSProperty不支持复杂的对象属性。它仅支持定义命令时ViewModel上存在的属性。这是因为复杂对象的生命周期是未知的,如果创建了该对象的多个实例,就会产生内存泄漏。我的建议是这样定义您的财产:
private Pessoa _pessoa;
public Pessoa Pessoa
{
get { return _pessoa; }
set
{
if (_pessoa != null)
_pessoa.PropertyChanged -= PropertyChanged;
SetProperty(ref _pessoa, value);
if (_pessoa != null)
_pessoa.PropertyChanged += PropertyChanged;
}
}
然后在PropertyChanged方法中,调用DelegateCommand.RaiseCanExecuteChanged
编辑:
复杂属性支持现在在Prism for Xamarin.Forms 7.0中可用。DelegateCommand.ObserveSProperty确实不支持复杂对象,但它是命令用于Prism的方式。在我看来,手动调用PropertyChanged是一种丑陋的黑客行为,应该避免。此外,它还会使Prism试图减少的代码再次膨胀 另一方面,将复杂类型的所有属性移动到ViewModel中会降低ViewModel的可读性。在这样的场景中创建复杂类型的原因首先是为了避免有太多的单一属性 但是,您可以将命令定义移到复杂类型中。然后,您可以为复杂类型的构造函数中的所有简单属性设置ObservesProperty,并且一切都按预期工作 型号:
使用Prism.Commands;
使用Prism.Mvvm;
使用静态System.String;
公共类LoginData:BindableBase
{
公共登录数据()
{
DbAddr=DbName=DbUser=DbPw=“”;
TestDbCommand=新的DelegateCommand(TestDbConnection、CanTestDbConnection)
.observeProperty(()=>DbAddr)
.observeProperty(()=>DbName)
.observeProperty(()=>DbUser)
.观测属性(()=>DbPw);
}
公共DelegateCommand TestDbCommand{get;set;}
公共bool CanTestDbConnection()
{
return!IsNullOrWhiteSpace(DbAddr)
&&!IsNullOrWhiteSpace(DbName)
&&!IsNullOrWhiteSpace(DbUser)
&&!IsNullOrWhiteSpace(DbPw);
}
public void TestDbConnection()
{
var t=新线程(委托(){
Status=DatabaseFunctions.TestDbConnection(this);
});
t、 Start();
}
私有字符串_dbAddr;
公共字符串DbAddr
{
get=>\u dbAddr;
set=>SetProperty(ref _dbAddr,value);
}
...
}
视图模型:
公共类数据库配置视图模型
{
公共数据库配置ViewModel()
{
CurrentLoginData=新的LoginData(真);
}
公共登录数据CurrentLoginData{get;set;}
}
查看:
IP地址订购器URL:
...
马鞭草
在我的Prism版本(7.0.0.362)中,您可以使用ObserveCanExecute,并传递在实体的每次属性更改时更新的属性更改
TestDbCommand = new DelegateCommand(TestDbConnection).ObservesCanExecute(() => HasChanged);
Pessoa = new Pessoa();
Pessoa.PropertyChanged += Pessoa_PropertyChanged;
然后在构造函数中使用验证方法更新HasChanges,并在析构函数中分离该方法
private void Pessoa_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
HasChanged = ValidatePessoa(Pessoa);
}
~YourViewModel()
{
Pessoa.PropertyChanged -= Pessoa_PropertyChanged;
}
bool _hasChanged;
public bool HasChanged { get => _hasChanged; set => SetProperty(ref _hasChanged, value); }
@布莱恩,你试过了吗?这种方法似乎不适合我。@是的,这是我在这个场景中使用的方法。您模型中的属性必须调用PropertyChanged才能工作。@Brian您说得对,我忘记为“模型”属性实现INPC。顺便问一下,你为什么要这样做
private void Pessoa_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
HasChanged = ValidatePessoa(Pessoa);
}
~YourViewModel()
{
Pessoa.PropertyChanged -= Pessoa_PropertyChanged;
}
bool _hasChanged;
public bool HasChanged { get => _hasChanged; set => SetProperty(ref _hasChanged, value); }