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

时间:2010-04-01 10:54:00

标签: .net wpf data-binding

如何有一个用于编辑带绑定的类属性的对话框,并在对话框中使用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实例不会更改。

3 个答案:

答案 0 :(得分:3)

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

您必须在绑定上设置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(); 

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

答案 1 :(得分:2)

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

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

<CheckBox IsChecked="{Binding MyProperty, UpdateSourceTrigger=Explicit}"/>

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

foreach (var be in BindingOperations.GetSourceUpdatingBindings(this))
{
    be.UpdateSource();
}

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

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

答案 2 :(得分:1)

您的NewsServer对象的原始实例未更改,因为您尚未对其进行实际修改。调用构造函数后,您将拥有以下三个NewsServer引用:

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)

请记住,对象是引用类型,在_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;
}

如果取消对话框,调用者将简单地忽略克隆的对象,因此ShowDialog()方法返回false。你可以重用DataContext属性,如上所示,或者你可以创建一个不同的属性(例如名为NewsServer),只返回DataContext属性值(即使代码稍微有点)更清楚对话类的公共接口。)