在对这个问题进行重大修改之后,我希望它现在已经清楚了。
当1次更改影响多个属性时,我在WPF中的绑定非常丢失。
我经常使用VVM将我的ViewModel绑定到我的View,我会说我没关系。
我正在尝试实现状态控制器。这意味着,无论我在UI的一部分中做了什么设置,反思都是彻底的。
例如,在我的UI部分,我可以打开或关闭功能,例如"显示图像"
当我进行此更改时,我希望通知我的应用程序中的所有内容并采取相应措施。
所以,我的StateController类将有一个属性
public bool ShowImages
在我看来,我可能会有像
这样的东西<image Visible ="{Binding ShowImages", Converter={StaticConverter ConvertMe}}" />
我遇到的问题是我如何让StateController警告我的所有ViewModel。
目前,在每个ViewModel中我假设我必须重复相同的属性
public bool ShowImages
EG
public class StateController : BaseViewModel
{
public bool ShowImages{get;set;}//imagine the implementation is here
}
public class ViewModelB : BaseViewModel
{
public bool ShowImages{}//imagine the implementation is here
}
public class ViewModelB : BaseViewModel
{
public bool ShowImages{}//imagine the implementation is here
}
所以,我的问题是,如果我更新了ViewModelB.ShowImages,我将如何首先通知StateController,而StateController又会更新所有ViewModel。
这是INotifyPropertyChanged能为我自动完成的事情,因为它们都共享相同的propertyName,或者我必须手动实现逻辑,例如
public static class StateController
{
public bool ShowImages{get;set;}//imagine the implementation is here
}
public class ViewModelA : BaseViewModel
{
public bool ShowImages
{
get { return StateController.ShowImages; }
set { StateControllerShowImages = value;
OnPropertyChanged("ShowImages"); }
}
}
public class ViewModelB : BaseViewModel
{
public bool ShowImages
{
get { return StateController.ShowImages; }
set { StateControllerShowImages = value;
OnPropertyChanged("ShowImages"); }
}
}
我讨厌上述实现的想法,但它确实展示了我想要实现的目标。我只希望有更好的方法!
答案 0 :(得分:1)
为了避免代码重复,您可以创建一个派生自BaseViewModel
的类来实现您的属性,并ViewModelA
,ViewModelB
扩展它。但是,这并没有解决保持每个实例更新的问题。
为此,您可以:
ShowImages
绑定属性,并通过订阅ShowImagesChanged
事件进行更新。这可以通过从UI执行的命令发布。我说这是WPF方法,并且有利于将ShowImages
州管理与其消费分离。ShowImages
更新责任分配给单个ViewModel,并在其他ViewModel中订阅其PropertyChanged
,以便相应地更新。比第一种选择更好,但仍然是巨大的耦合。答案 1 :(得分:1)
仅为该对象模型引发PropertyChange通知。
因此,提出"Name"
ClassA
属性的更改通知只会在绑定到特定ClassA.Name
的情况下更新UI。它不会触发任何ClassB.Name
或ClassA.Name
的其他实例的更改通知。
我建议您在StateModel
使用单身人士,并让其他模型订阅StateModel.PropertyChanged
事件,以了解它是否应该更新,例如this answer。
public ViewModelA
{
public ViewModelA()
{
StateController.Instance.PropertyChanged += StateController_PropertyChanged;
}
void StateController_PropertyChanged(object sender, NotifyPropertyChangedEventArgs e)
{
// if singleton's ShowImages property changed, raise change
// notification for this class's ShowImages property too
if (e.PropertyName == "ShowImages")
OnPropertyChanged("ShowImages");
}
public bool ShowImages
{
get { return StateController.Instance.ShowImages; }
set { StateController.Instance.ShowImages = value; }
}
}
答案 2 :(得分:1)
如果我理解正确,您正在寻找一种机制,允许您的不同ViewModel相互通信。
一种可能的方法是实现观察者模式(可在此处找到代码示例:"Observer pattern with C# 4")。通过这种方式,您的ViewModel相互订阅以接收来自“发布者”的更改通知,即其值已更改的ViewModel。您可以很好地控制谁从哪个发布者收到哪个通知。这种方法的缺点是模型之间的紧密耦合。
我的方法是:
使用邮件调度程序。您的ViewModel可以订阅某种类型的消息,例如ShowImagesChanged
。如果您的任何ViewModel更改了ShowImages
属性,则该ViewModel会调度调度程序以使用您当前的值发送此类ShowImagesChanged
消息。
通过这种方式,您可以让ViewModels彼此分离。尽管如此,虽然ViewModel彼此不了解,但它提供了一种在它们之间交换数据的方法。
就个人而言,我已多次使用Caliburn Micro MVVM框架,但应该有足够的其他MVVM框架提供相同的功能以满足您的需求。
Calibiurn Micro文档以及调度程序的使用方式如下:Event Aggregator
答案 3 :(得分:0)
为什么要重复属性?只需绑定到StateController
本身。
假设我们有单身StateController
:
public class StateController : INotifyPropertyChanged
{
private static StateController instance;
public static StateController Instance {
get { return instance ?? (instance = new StateController()); }
}
//here`s our flag
private bool isSomething;
public bool IsSomething
{
get { return isSomething; }
set
{
isSomething = value;
PropertyChanged(this, new PropertyChangedEventArgs("IsSomething"));
}
}
private StateController(){}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
}
然后在基本VM类中,只需引用此控制器:
public StateController Controller { get { return StateController.Instance; } }
在需要的地方绑定如下:
<CheckBox IsChecked="{Binding Controller.IsSomething}">
Test
</CheckBox>
这样每个绑定都可以使用一个属性并对一个属性做出反应。如果您需要一些自定义代码,您可以根据需要订阅PropertyChanged
StateController
并采取措施。