c# - WPF:使用接口作为 DataContext 而不是实现 INotifyPropertyChanged 的对象
问题描述
我重构了我的 WPF 应用程序,以便 DataContexts 不再是某个实现的类的实例,INotifyPropertyChanged
而是我的一些自定义接口。实现每个自定义接口的对象也需要实现INotifyPropertyChanged
。但我不能再在构建时强制执行此要求。我不确定这是否是个好主意。
例如,考虑以下简单的类层次结构
// Base view model class has stock implementation of INotifyPropertyChanged.
public BaseViewModel : INotifyPropertyChanged
{
// Assume INotifyPropertyChanged implementation with this utility to raise the event
void RaisePropertyChanged(string property) { // ...blah blah blah ... }
}
// Interface for nameable object
public interface INameable
{
string Name { get; set; }
}
// View model for nameable object
public class NameableViewModel : BaseViewModel, INameable
{
private string _name;
public string Name
{
get => _name;
set
{
if (value == _name) return;
_name = value
RaisePropertyChanged();
}
}
// Main view model exposes named object by interface, NOT by view-model
public class MainViewModel : BaseViewModel
{
public INameable NameableObject { get; set; }
}
这是一个视图绑定,INameable
而不是NameableViewModel
<UserControl x:Class="MyView"
(... blah blah blah... namespace declarations...)
d:DataContext="{d:DesignInstance MainViewModel}">
<TextBox DataContext={Binding NameableObject.Name, Mode=TwoWay}"/>
</UserControl>
这在 WPF 中运行良好,因为它查询任何数据上下文INotifyPropertyChanged
。它接收到 PropertyChanged 通知,即使它得到的只是INameable
. 但是如果我忘记正确设置我的类,WPF 将永远不会收到属性更改通知。我最终可能会遇到需要一段时间才能注意到或跟踪的错误(此处的测试资源有限)。
此外,在我的代码隐藏中,我有时会通过 INotifyPropertyChanged
使用 Josh Smith 出色的PropertyObserver
.
public class PropertyObserver<TPropertySource>
: IWeakEventListener
where TPropertySource : INotifyPropertyChanged
{
... blah blah blah..
}
这确实需要在构建时使用 INotifyPropertyChanged,这在我使用 BaseViewModel 实例时非常有用。但是现在我只有一个接口,我必须自己查询它并依靠运行时错误来让我知道我搞砸了。
这引出了我的问题。一个通用的,一个非常具体的:
- 这种设计合理吗?它是在 WPF 中工作的人在实践中经常做的事情吗?或者,确定我用作数据上下文的任何类型是否已经声明为实现 INotifyPropertyChanged 总是更好?(我意识到我可能在这个问题上思考得太像 C++ 程序员了)
- 假设在我的代码中,我转换了一个对象,但它不支持我需要的接口,我想抛出一个异常。我应该抛出什么特定的 .NET 异常?什么最合适?
NotSupportedException
? 还有什么?
解决方案
我不完全确定您所指的“设计”或“实践”是什么。我没有看到一般模式,只有接口的特定用途,我不清楚它的用途。
根据我的经验,最好让视图模型尽可能简单。在某些情况下,它们甚至不需要实现INotifyPropertyChanged
(想想只读视图模型)。通常,我使用提供ViewModelBase
. 几乎我制作的每个视图模型都派生自ViewModelBase
,并且视图模型只包含 setter、getter 和命令。
对于您的第二个问题,我认为具体的例外情况取决于使用界面的意图。但也许一个普遍的例外可能是InvalidOperationException
.
推荐阅读
- javascript - firestore 返回 promise 而不是给出值
- sas - SAS重复行和转置数据
- machine-learning - 获取用户警告:测试/验证数据集列“browser_name”的级别未经过训练:H2O GBM 模型的 [Android、Midori、Opera Mini、其他]
- react-native - 此版本的 IntelliJ IDEA(或 Android Studio)的 Android Support 插件无法打开此项目,请使用 4.2 版本重试
- postgresql - PostgreSQL 聚合和过滤
- html - 为什么当我按下“tab”键时我的响应式导航栏被选中?
- python - 使用 for 语句在列表中查找特定模式
- java - Android 资源链接失败:values.xml
- gradle - 无法在使用 kotlin dsl 的 scala-java polyglot gradle 项目中的 java 编码中使用 scala 类
- asp.net-core - OkObjectResult 到 Model 类型转换