.net 编辑对话框,带有绑定和WPF中的OK/Cancel

.net 编辑对话框,带有绑定和WPF中的OK/Cancel,.net,wpf,data-binding,.net,Wpf,Data Binding,如何创建一个对话框来编辑具有绑定的类的属性,并在对话框中设置OK Cancel 我的第一个想法是: public partial class EditServerDialog : Window { private NewsServer _newsServer; public EditServerDialog(NewsServer newsServer) { InitializeComponent(); this.DataContext = (_

如何创建一个对话框来编辑具有绑定的类的属性,并在对话框中设置OK Cancel

我的第一个想法是:

public partial class EditServerDialog : Window {
    private NewsServer _newsServer;

    public EditServerDialog(NewsServer newsServer) {
        InitializeComponent();

        this.DataContext = (_newsServer = newsServer).Clone();
    }

    private void ButtonClick(object sender, RoutedEventArgs e)
    {
        switch (((Button)e.OriginalSource).Content.ToString()) {
            case "OK":
                _newsServer = (NewsServer)this.DataContext;
                this.Close();
                break;
            case "Cancel":
                this.Close();
                break;
        }
    }
}

当切换为“OK”时,DataContext包含正确的信息,但最初传递的NewsServer实例不会更改

您的
新闻服务器
对象的原始实例没有更改,因为您没有实际修改它。调用构造函数后,您有以下三个
newserver
引用:

newsServer = original instance
_newsServer = original instance
DataContext = clone of original instance
单击“确定”按钮后,参考将如下所示:

newsServer = original instance
_newsServer = clone of original instance (possibly modified)
DataContext = clone of original instance (possibly modified)
请记住,对象是引用类型,在分配给
\u newserver
时,您只更新其引用,而不是对象本身的值

为了允许更新
NewsServer
对象本身,我想到了两个选项,其他选项可能存在,第一个可能是最简单的

  • 新闻服务器
    对象上实现
    无效更新(新闻服务器源)
    方法,然后对
    新闻服务器
    字段执行新赋值,而不是对其调用更新方法并传递
    数据上下文
    参考值
  • 使用公共/内部属性公开
    \u newserver
    值。您可以通过多种机制来利用这一点:显式响应属性值更改时引发的事件;绑定到属性(例如,使其成为依赖项属性或实现
    INotifyPropertyChanged
    );或者,如果
    ShowDialog()
    方法返回值为
    true
    ,则调用方只需检索该值即可
请注意,如果您将一点逻辑推回到调用方,您的对话类可能会更简单。特别是,一种方法是仅维护通过属性向调用者公开的克隆对象(例如,完全去掉
\u newserver
字段,只使用
DataContext
)。该对象将像以前一样绑定到对话框的元素。调用方只需从
ShowDialog()
方法中检索
true
结果上的该实例引用

例如:

NewsServer newsServer = ...;
EditServerDialog editServerDialog = new EditServerDialog(newsServer);

if (editServerDialog.ShowDialog() == true)
{
    newsServer = editServerDialog.DataContext;
}

如果对话框被取消,调用方将忽略克隆的对象,因此
ShowDialog()
方法返回
false
。您可以重复使用如上所示的
DataContext
属性,也可以创建一个只返回
DataContext
属性值的不同属性(例如名为
NewsServer
)(即使代码对dialog类的公共接口更清晰).

这是一个老问题,但我会为未来的读者回答

您必须在绑定上设置
UpdateSourceTrigger=“Explicit”
,以便在用户单击“确定”之前它们不会更新实际的源代码。然后在OK按钮处理程序上,您可以编写:

BindingExpression be = MyTextBox.GetBindingExpression(TextBox.TextProperty);  
if (be!=null) be.UpdateSource(); 
另外,如果要将绑定重置为初始状态,请使用

BindingExpression be = MyTextBox.GetBindingExpression(TextBox.TextProperty);  
if (be!=null) be.UpdateTarget(); 

如果您的对话框很复杂,您可能希望递归地遍历它的所有控件。

这是一个老问题,但我最近遇到了这个问题,发现有更好的方法使用.NET 4.5来处理它

首先,将绑定UpdateSourceTrigger标记为显式:

<CheckBox IsChecked="{Binding MyProperty, UpdateSourceTrigger=Explicit}"/>
GetSourceUpdateBindings是.NET 4.5中的一个新方法


取消按钮不需要执行任何操作,因为绑定已标记为显式,并且仅在调用UpdateSource时才会“提交”

如果显示绑定设置,可能会有所帮助。绑定示例:{binding NeedAuthentication,UpdateSourceTrigger=LostFocus,Mode=TwoWay}。绑定是正确的,因为this.DataContext包含正确的数据。我应该如何执行此操作并仍然能够取消和/或应用?
foreach (var be in BindingOperations.GetSourceUpdatingBindings(this))
{
    be.UpdateSource();
}