WPF、MVVM设计冗长绑定的考虑
WPF, MVVM design lengthy binding consideration
我目前正在编写一个 WPF 应用程序,使用 MVVM 方法和 Entity Framework。
在我的 MainVindow.xaml 中,左侧有一个导航系统。
对于它的每个导航项,都有一个相应的用户控件。
单击其中一项会在主 window.
右侧显示用户控件
我对每个用户控件都有一个视图模型。
我将 MainWindow.xaml 绑定到 MainViewModel class 的一个实例。
每个用户控件都绑定到存储在我的 MainViewModel 中的相应视图模型的实例 class。
在每个用户控件视图模型的构造函数中,我传递了 MainViewModel。
想法是在所有这些视图模型之间共享一个实体:
class MainViewModel
{
public SharedEntity MySharedEntity
{
get
{
return _mySharedEntity;
}
set
{
InpcLogic(_mySharedEntity);
}
}
public FirstUserControlViewModel MyFirstUserControlViewModel
{
get
{
if (_myFirstUserControlViewModel == null)
_myFirstUserControlViewModel = new FirstUserControlViewModel(this);
return _myFirstUserControlViewModel;
}
}
}
这样,在 FirstUserControlViewModel 实例中,我可以这样访问 MySharedEntity:
class FirstUserControlViewModel
{
MainViewModel _mainViewModel;
public MainViewModel MyMainViewModel
{
get
{
return _mainViewModel;
}
}
public SharedEntity MyMainViewmodelSharedEntity
{
get
{
return _mainViewModel.MySharedEntity;
}
}
public FirstUserControlViewModel(MainViewModel mainViewModel)
{
_mainViewModel = mainViewModel;
}
}
在我的用户控件 xaml(绑定到上面的视图模型)中,我可以将控件从我的 mainViewModel 绑定到这个共享实体。
现在,这是我的问题:当我从应用程序中的任何位置更改共享实体时,绑定并不总是在用户控件级别上刷新。会不会是因为INPC逻辑在主视图模型而不是用户控件视图模型?
假设我在第一个用户控件中绑定了一个文本块,如下所示:
<TextBox Text="{Binding MyMainViewModel.MySharedEntity.AnyStringMember,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
它工作正常。
但是,如果我执行以下操作
<TextBox Text="{Binding MyMainViewmodelSharedEntity.AnyStringMember,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
然后,当我更改共享实体时,绑定不会刷新。在这两种情况下,它对我的实体使用相同的引用,不是吗?
**
更新
**
这是我最终要做的事情:
在我的 MainViewModel 中,我有以下 属性:
public class MainViewModel
{
EntityFrameworkClass _myPrivateEfObject;
EntityFrameworkNavigationPropertyClass _myPrivateEfNavigationPropertyObject;
public EntityFrameworkClass MyPublicEfObject
{
get
{
return _myPrivateEfObject;
}
set
{
InpcLogic(ref _myPrivateEfObject, value);
MyPublicEfNavigationPropertyObject = _myPrivateEfObject.EntityFrameworkNavigationPropertyClass.FirstOrDefault();
}
}
public EntityFrameworkNavigationPropertyClass MyPublicEfNavigationPropertyObject
{
get
{
return _myPrivateEfNavigationPropertyObject;
}
set
{
InpcLogic(ref _myPrivateEfNavigationPropertyObject, value);
}
}
}
然后在我的用户控件xaml中,我简单地使用MainViewModel.MyPublicEfNavigationPropertyObject
您需要调用实现INotifyPropertyChanged
的方法。在您的情况下,您希望它在您的 MySharedEntity
上实现,然后在 AnyStringMember
的 setter 上实现 RaisePropertyChanged
。
我将我的文本框绑定到 属性,它不实现任何 INPC 行为。是的,它指的是同一个对象,但是如果没有实现INPC行为,就无法通知图形组件需要刷新。
我将绑定到我的 MainViewModel 中的属性并在其中实施 INPC。
我目前正在编写一个 WPF 应用程序,使用 MVVM 方法和 Entity Framework。
在我的 MainVindow.xaml 中,左侧有一个导航系统。 对于它的每个导航项,都有一个相应的用户控件。 单击其中一项会在主 window.
右侧显示用户控件我对每个用户控件都有一个视图模型。 我将 MainWindow.xaml 绑定到 MainViewModel class 的一个实例。
每个用户控件都绑定到存储在我的 MainViewModel 中的相应视图模型的实例 class。
在每个用户控件视图模型的构造函数中,我传递了 MainViewModel。
想法是在所有这些视图模型之间共享一个实体:
class MainViewModel
{
public SharedEntity MySharedEntity
{
get
{
return _mySharedEntity;
}
set
{
InpcLogic(_mySharedEntity);
}
}
public FirstUserControlViewModel MyFirstUserControlViewModel
{
get
{
if (_myFirstUserControlViewModel == null)
_myFirstUserControlViewModel = new FirstUserControlViewModel(this);
return _myFirstUserControlViewModel;
}
}
}
这样,在 FirstUserControlViewModel 实例中,我可以这样访问 MySharedEntity:
class FirstUserControlViewModel
{
MainViewModel _mainViewModel;
public MainViewModel MyMainViewModel
{
get
{
return _mainViewModel;
}
}
public SharedEntity MyMainViewmodelSharedEntity
{
get
{
return _mainViewModel.MySharedEntity;
}
}
public FirstUserControlViewModel(MainViewModel mainViewModel)
{
_mainViewModel = mainViewModel;
}
}
在我的用户控件 xaml(绑定到上面的视图模型)中,我可以将控件从我的 mainViewModel 绑定到这个共享实体。
现在,这是我的问题:当我从应用程序中的任何位置更改共享实体时,绑定并不总是在用户控件级别上刷新。会不会是因为INPC逻辑在主视图模型而不是用户控件视图模型?
假设我在第一个用户控件中绑定了一个文本块,如下所示:
<TextBox Text="{Binding MyMainViewModel.MySharedEntity.AnyStringMember,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
它工作正常。
但是,如果我执行以下操作
<TextBox Text="{Binding MyMainViewmodelSharedEntity.AnyStringMember,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
然后,当我更改共享实体时,绑定不会刷新。在这两种情况下,它对我的实体使用相同的引用,不是吗?
**
更新
**
这是我最终要做的事情:
在我的 MainViewModel 中,我有以下 属性:
public class MainViewModel
{
EntityFrameworkClass _myPrivateEfObject;
EntityFrameworkNavigationPropertyClass _myPrivateEfNavigationPropertyObject;
public EntityFrameworkClass MyPublicEfObject
{
get
{
return _myPrivateEfObject;
}
set
{
InpcLogic(ref _myPrivateEfObject, value);
MyPublicEfNavigationPropertyObject = _myPrivateEfObject.EntityFrameworkNavigationPropertyClass.FirstOrDefault();
}
}
public EntityFrameworkNavigationPropertyClass MyPublicEfNavigationPropertyObject
{
get
{
return _myPrivateEfNavigationPropertyObject;
}
set
{
InpcLogic(ref _myPrivateEfNavigationPropertyObject, value);
}
}
}
然后在我的用户控件xaml中,我简单地使用MainViewModel.MyPublicEfNavigationPropertyObject
您需要调用实现INotifyPropertyChanged
的方法。在您的情况下,您希望它在您的 MySharedEntity
上实现,然后在 AnyStringMember
的 setter 上实现 RaisePropertyChanged
。
我将我的文本框绑定到 属性,它不实现任何 INPC 行为。是的,它指的是同一个对象,但是如果没有实现INPC行为,就无法通知图形组件需要刷新。
我将绑定到我的 MainViewModel 中的属性并在其中实施 INPC。