编辑对话框,带有绑定和WPF中的确定/取消

Eri*_*kTJ 6 .net data-binding wpf

如何使用绑定来编辑类的属性,并在对话框中使用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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在交换机中,情况"OK",DataContext包含正确的信息,但最初传递的NewsServer实例不会更改.

Dav*_*rez 6

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

首先,将您的绑定 UpdateSourceTrigger 标记为 Explicit:

<CheckBox IsChecked="{Binding MyProperty, UpdateSourceTrigger=Explicit}"/>
Run Code Online (Sandbox Code Playgroud)

然后,在您的 Ok 按钮单击事件处理程序中使用:

foreach (var be in BindingOperations.GetSourceUpdatingBindings(this))
{
    be.UpdateSource();
}
Run Code Online (Sandbox Code Playgroud)

GetSourceUpdatingBindings 是 .NET 4.5 中的一个新方法。

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


Pom*_*oma 5

老问题,但我会为未来的读者回答......

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

BindingExpression be = MyTextBox.GetBindingExpression(TextBox.TextProperty);  
if (be!=null) be.UpdateSource(); 
Run Code Online (Sandbox Code Playgroud)

另外,如果您想将绑定重置为初始状态,请使用

BindingExpression be = MyTextBox.GetBindingExpression(TextBox.TextProperty);  
if (be!=null) be.UpdateTarget(); 
Run Code Online (Sandbox Code Playgroud)

如果您的对话框很复杂,您可能需要递归地遍历其所有控件。


Ric*_*ire 1

对象的原始实例NewsServer并未更改,因为您尚未实际修改它。调用构造函数后,您将获得以下三个NewsServer引用:

newsServer = original instance
_newsServer = original instance
DataContext = clone of original instance
Run Code Online (Sandbox Code Playgroud)

单击“确定”按钮后,引用将如下:

newsServer = original instance
_newsServer = clone of original instance (possibly modified)
DataContext = clone of original instance (possibly modified)
Run Code Online (Sandbox Code Playgroud)

请记住,对象是引用类型,在您的分配中_newsServer仅更新其引用,而不是对象本身的值。

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

  • 然后在对象上实现一个void Update(NewsServer source)方法,NewsServer而不是对字段执行新的赋值,_newsServer而是调用其更新方法并传入DataContext引用值。
  • _newsServer使用公共/内部属性公开该值。您可以通过多种机制来利用它:显式响应属性值更改时引发的事件;绑定到属性(例如,使其成为依赖属性或实现INotifyPropertyChanged);或者只是期望调用者在该ShowDialog()方法返回值为 时检索该值true

请注意,如果您将一些逻辑推回到调用者身上,您的对话框类可能会更简单。特别是,一种方法是维护克隆的对象,通过属性向调用者公开(例如完全删除该_newsServer字段并仅使用DataContext)。该对象将像以前一样绑定到对话框的元素。调用者只需true从该ShowDialog()方法的结果中检索该实例的引用即可。

例如:

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

if (editServerDialog.ShowDialog() == true)
{
    newsServer = editServerDialog.DataContext;
}
Run Code Online (Sandbox Code Playgroud)

如果取消对话框,则调用者将忽略克隆的对象,因此该ShowDialog()方法返回false。您可以重用DataContext如上所示的属性,或者您可以创建一个NewsServer仅返回DataContext属性值的不同属性(例如,named)(即,使代码对于对话框类的公共接口更加清晰)。