最近我一直在学习C#和WPF。我试图在我正在进行的项目中使用MVVM,只是为了使代码组织起来,并了解它是如何工作的。
在MVVM中,视图绑定上的控件绑定到ViewModel上的属性,该属性实现了INotifyPropertyChanged。通常情况下,当某个属性被更新时,我希望得到一组其他属性的更新结果。
例如,我有一个ListBox,上面有一个TextBox。您可以输入TextBox,它会过滤ListBox中的内容。但在某些情况下,我还需要能够从代码中清除TextBox。代码最后看起来是这样的:
private Collection<string> _listOfStuff;
public Collection<string> FilteredList
{
get
{
if (String.IsNullOrWhiteSpace(SearchText))
{
return _listOfStuff;
}
else
{
return new Collection<string>(_listOfStuff.Where(x => x.Contains(SearchText)));
}
}
set
{
if (value != _listOfStuff)
{
_listOfStuff = value;
OnPropertyChanged("FilteredList");
}
}
}
private string _searchText;
public string SearchText
{
get { return _searchText; }
set
{
if (value != _searchText)
{
_searchText = value;
OnPropertyChanged("SearchText"); // Tells the view to change the value of the TextBox
OnPropertyChanged("FilteredList"); // Tells the view to update the filtered list
}
}
}随着这个项目的规模越来越大,这个项目开始感到草率。我有一个设置者,有6个调用到OnPropertyChanged,这是很难保持跟踪的东西。有更好的方法吗?
发布于 2015-12-03 19:50:29
大约一年前,我在一个项目中试用了Assisticant。它会指出哪些属性需要发出通知,哪些属性是相关的。在Pluralsight上有一个很好的课程,网站上的例子也很好。如果没有其他的东西,您可以查看源代码,看看他是如何做到的。
同时也有一些来自MVVM层次结构中的更改通知的好建议。
他们提到:
使用属性->,例如DependsUpon(名称(大小))
和
乔希·史密斯的PropertyObserver
如果每次只需要引发相同的通知,则可以将raise属性更改调用放入方法中。
发布于 2015-12-03 18:29:13
首先,您不应该在命令中执行可能昂贵的操作,然后您将能够从您的OnPropertyChanged("FilteredList");中删除该SearchText。
因此,您应该将该代码从getter移动到它自己的命令中,并从XAML绑定它(要么作为按钮上的命令,要么使用混合交互触发器在文本字段值更改时调用它)。
public ICommand SearchCommand { get; protected set; }
// Constructor
public MyViewModel()
{
// DelegateCommand.FromAsyncHandler is from Prism Framework, but you can use
// whatever your MVVM framework offers for async commands
SearchCommand = DelegateCommand.FromAsyncHandler(DoSearch);
}
public async Task DoSearch()
{
var result = await _listOfStuff.Where(x => x.Contains(SearchText)).ToListAsync();
FilteredList = new Collection<string>(result);
}
private Collection<string> _listOfStuff;
private Collection<string> _filteredList;
public Collection<string> FilteredList
{
get
{
return _filteredList;
}
set
{
if (value != _filteredList)
{
_filteredList = value;
OnPropertyChanged("FilteredList");
}
}
}
private string _searchText;
public string SearchText
{
get
{
return _searchText;
}
set
{
if (value != _searchText)
{
_searchText = value;
OnPropertyChanged("SearchText");
}
}
}On :当您重命名您的属性时,您也可以使用OnPropertyChanged(nameof(FilteredList));拥有一个重构友好版本,所有的OnPropertyChanged调用都将更新到。虽然需要VisualStudio6.0,但它与旧的C#框架(回到2.0)兼容,但需要VisualStudio2015或更高版本
发布于 2017-11-07 15:29:53
对于任何寻找这类问题的好解决方案的人,请查看ReactiveUI。
它是一个基于反应性扩展(Rx)的框架,它的思想是在没有大量RaisePropertyChanged(..)的情况下,显式地对属性之间的这种类型的依赖关系建模。
特别是查看ObservableAsPropertyHelper (有时称为OAPH)。
https://stackoverflow.com/questions/34072156
复制相似问题