我使用CompositeWPF使用C#创建应用程序。这真的应该对答案产生影响,因为我的问题会出现在Prism之外。
我有一个ItemsControl,它绑定到包含我的ViewModels的ObservableCollection。这工作正常。在我的DataTemplate中,我将所需的控件绑定在XAML中。其中一个控件是一个名为“Configure”的按钮。单击该按钮时,会发出一个DelegateCommand,它将ViewModel作为参数传递。
DelegateCommand打开一个模态对话框,显示VM如下所示。
private void ShowDialog(object obj)
{
ComPortPropertiesPresenter presenter = _container.Resolve<ComPortPropertiesPresenter>();
ComPortViewModel vm = obj as ComPortViewModel;
presenter.ComPort = vm.Clone() as ComPortViewModel;
DialogOptions options = new DialogOptions();
options.DialogTitle = presenter.View.DisplayName;
options.HideOkCancelButtons = true;
bool? result = DialogWorkspace.ShowView(presenter.View, options, () =>
{
return true;
});
if (result == true)
{
// TODO: There must be a better way of doing this. The problem is if you bind the object the
// automated bindings cause a realtime update. If you clone the object and then set it to become obj then
// the bindings do not update. Need to investigate how an observablecollection triggers an update.
int position = ComPorts.IndexOf(obj as ComPortViewModel);
ComPorts.Remove(obj as ComPortViewModel);
ComPorts.Insert(position, presenter.ComPort);
}
我的原始代码将obj传递给没有克隆的演示者。问题在于价值实时变化。如果您进行了更改,然后点击取消,则会关闭对话框,但由于绑定,更改已经发生。
我决定克隆vm并将其传递给视图。如果对话结果为真,我尝试将克隆的vm复制到原始文件上。 EG:obj = presenter.ComPort;
然后,这不会更新包含按钮的原始视图上的值。
然后我尝试了类似... obj.BaudRate = presenter.ComPort.BaudRate这样的工作虽然我很担心,但是如果vm被延长了,那么事情就会被遗漏。
我的最终解决方案是删除原始vm并在原始位置添加新的vm。虽然我觉得它有点笨拙,但它的工作效率为100%。我是否过于批评或者有更好的方法吗?
我的猜测是,当添加/删除某些内容时,ObservableCollection会触发一个INotify事件。在我的虚拟机中,当一个属性被更新时它也一样,因为我引发了一个事件。
问题是,如果你在ObservableCollection中覆盖某些东西,那么不会引发任何事件吗?
必须有一些知道的聪明的障碍。
答案 0 :(得分:2)
这里你需要理解的是指针而不是WPF。
您的“obj”变量只是内存中对象的存储地址。在您的示例中,有2个对此对象的引用。第一个是你的obj变量,第二个是你的ObservableCollection。
我们这样说吧。让我们将原始对象命名为“A”,将新对象命名为“B”。目前您的参考文件如下所示:
obj => A
ObservableCollection => A
presenter.ComPort => B
当你说obj = presenter.ComPort时,你真的在说“我不再想引用对象'obj'指向...现在我想引用对象'presenter.ComPort'指向” 。现在一切都是这样的:
obj => B
ObservableCollection => A
presenter.ComPort => B
注意你没有对ObservableCollection做任何事情。这解决了你的问题“如果你覆盖某些东西......没有引发任何事件”......你没有“覆盖”任何东西。
这就是您必须执行Remove + Add来更改ObservableCollection的原因。当你这样做时,你现在已经改变了ObservableCollection中的内容:
obj => B
ObservableCollection => B
presenter.ComPort => B
没有办法解决这个问题,你所做的是正确的。这是参考文献的本质。
通过使用“引用引用”(使用“ref”关键字传递引用)可以解决这个问题,但我真的很喜欢你在这里所做的事情,我建议你保留它。