在一个 ViewModel 中更新单例对象(统一),在其他 ViewModel 更新中具有绑定
Update singleton object (unity) in one ViewModel, have binding in other ViewModel update
我将 PRISM 与 Unity 容器一起使用。
假设我有 3 个模块,模块 A、模块 B 和 UserModule。 UserModule 跟踪当前用户及其权限,模块 A 有一个 View/VM,其中包含一个包含所有可用用户的 ComboBox,模块 B 有一个 View/VM,仅显示当前选定用户的名称。
UserModule 注册了一个 UserService 的单例实例,它管理用户并提供改变当前用户的方法。
UserModule.cs
/// Create and register instance of laser service
this.container.RegisterType<IUserService,UserService>(new ContainerControlledLifetimeManager());
模块 A - HeaderViewModel.cs
public class HeaderViewModel : BindableBase
{
private readonly IUserService _userService;
private List<IUser> users;
private IUser curUser;
public HeaderViewModel(IUserService userService)
{
_userService = userService;
users = _userService.GetUsers();
curUser = _userService.CurUser;
}
public List<IUser> Users
{
get { return users; }
}
public IUser CurUser
{
get { return curUser; }
set
{
SetProperty<IUser>(ref curUser, value);
_userService.CurUser=curUser;
}
}
}
模块 A - HeaderView.xaml
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<TextBlock Text="{Binding CurUser.Name, Mode=TwoWay}"></TextBlock>
<TextBlock Text="Users: "></TextBlock>
<ComboBox ItemsSource="{Binding Users, Mode=TwoWay}" SelectedItem="{Binding CurUser, Mode=TwoWay}" ></ComboBox>
</StackPanel>
以上所有工作正常,HeaderView.xaml
加载时填充了 ComboBox,当我更改用户时,它会更新显示当前用户名的 TextBlock,并更新当前用户对象用户服务单例。
现在,如果我有来自模块 B 的另一个显示当前用户名的 View/VM
,它也应该会自动更新。但是,我还没有能够成功地让这个绑定起作用。
如果需要,我可以 post 更多代码,但我真正的问题是这种方法是否可行?如果每个用户都有特定的权限,并且某些控件基于这些权限来设置它们的 IsEnabled 属性,那么只需更新单例 UserService 对象中的当前用户并通过简单绑定,所有其他 views/vms
跨不同型号也会自动更新。这可能吗?或者我是否需要添加某种 "user changed" 事件并将其发布到所有需要更新其 UI 的视图模型?
谢谢
编辑 1
由于有人被动积极地似乎不理解我在问什么,我会澄清一下。如果 2 个单独的视图都使用相同的单例服务从中获取数据,当 View1 修改此数据时,View2 是否可能仅通过 xaml 绑定自动更新?例如,假设您有 2 个单独的视图,允许您通过 ComboBox 更改当前用户。当我更改 View1 上的用户时,是否可以通过适当的绑定让 View2 自动更新其选定的用户?
您可以通过让您的服务将数据更改通知其余应用程序来做到这一点。
一种可能性是让服务实现 INotifyPropertyChanged
,然后让每个视图模型在收到来自服务的通知时使用 the property observer 为自己的属性发布适当的通知。
根据应用程序的大小,您可能想要推出一些专用的 CQRS system,但对于我的桌面应用程序,PropertyObserver
通常效果很好并且提供了可理解且易于重构的功能代码。
只需将绑定上的模式设为 TwoWay。
我将 PRISM 与 Unity 容器一起使用。
假设我有 3 个模块,模块 A、模块 B 和 UserModule。 UserModule 跟踪当前用户及其权限,模块 A 有一个 View/VM,其中包含一个包含所有可用用户的 ComboBox,模块 B 有一个 View/VM,仅显示当前选定用户的名称。
UserModule 注册了一个 UserService 的单例实例,它管理用户并提供改变当前用户的方法。
UserModule.cs
/// Create and register instance of laser service
this.container.RegisterType<IUserService,UserService>(new ContainerControlledLifetimeManager());
模块 A - HeaderViewModel.cs
public class HeaderViewModel : BindableBase
{
private readonly IUserService _userService;
private List<IUser> users;
private IUser curUser;
public HeaderViewModel(IUserService userService)
{
_userService = userService;
users = _userService.GetUsers();
curUser = _userService.CurUser;
}
public List<IUser> Users
{
get { return users; }
}
public IUser CurUser
{
get { return curUser; }
set
{
SetProperty<IUser>(ref curUser, value);
_userService.CurUser=curUser;
}
}
}
模块 A - HeaderView.xaml
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<TextBlock Text="{Binding CurUser.Name, Mode=TwoWay}"></TextBlock>
<TextBlock Text="Users: "></TextBlock>
<ComboBox ItemsSource="{Binding Users, Mode=TwoWay}" SelectedItem="{Binding CurUser, Mode=TwoWay}" ></ComboBox>
</StackPanel>
以上所有工作正常,HeaderView.xaml
加载时填充了 ComboBox,当我更改用户时,它会更新显示当前用户名的 TextBlock,并更新当前用户对象用户服务单例。
现在,如果我有来自模块 B 的另一个显示当前用户名的 View/VM
,它也应该会自动更新。但是,我还没有能够成功地让这个绑定起作用。
如果需要,我可以 post 更多代码,但我真正的问题是这种方法是否可行?如果每个用户都有特定的权限,并且某些控件基于这些权限来设置它们的 IsEnabled 属性,那么只需更新单例 UserService 对象中的当前用户并通过简单绑定,所有其他 views/vms
跨不同型号也会自动更新。这可能吗?或者我是否需要添加某种 "user changed" 事件并将其发布到所有需要更新其 UI 的视图模型?
谢谢
编辑 1 由于有人被动积极地似乎不理解我在问什么,我会澄清一下。如果 2 个单独的视图都使用相同的单例服务从中获取数据,当 View1 修改此数据时,View2 是否可能仅通过 xaml 绑定自动更新?例如,假设您有 2 个单独的视图,允许您通过 ComboBox 更改当前用户。当我更改 View1 上的用户时,是否可以通过适当的绑定让 View2 自动更新其选定的用户?
您可以通过让您的服务将数据更改通知其余应用程序来做到这一点。
一种可能性是让服务实现 INotifyPropertyChanged
,然后让每个视图模型在收到来自服务的通知时使用 the property observer 为自己的属性发布适当的通知。
根据应用程序的大小,您可能想要推出一些专用的 CQRS system,但对于我的桌面应用程序,PropertyObserver
通常效果很好并且提供了可理解且易于重构的功能代码。
只需将绑定上的模式设为 TwoWay。