WPF绑定 - 必须有一个比我做得更好的方式!

时间:2009-10-28 14:37:07

标签: c# wpf binding prism

概述

我使用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中覆盖某些东西,那么不会引发任何事件吗?

必须有一些知道的聪明的障碍。

1 个答案:

答案 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”关键字传递引用)可以解决这个问题,但我真的很喜欢你在这里所做的事情,我建议你保留它。

相关问题