更新DependencyProperty之前的回调

时间:2013-11-06 08:57:13

标签: c# wpf listbox dependency-properties

我在WPB中有一个绑定到ObservableCollection的ListBox

public static readonly DependencyProperty ProgramsProperty =
       DependencyProperty.Register("Programs",
       typeof(ObservableCollection<ProgramData>), typeof(ProgramView),
                                                                                                                    new PropertyMetadata(default(ObservableCollection<ProgramData>)));
    public ObservableCollection<ProgramData> Programs
    {
        get { return (ObservableCollection<ProgramData>)GetValue(ProgramsProperty); }
        set { SetValue(ProgramsProperty, value); }
    }

并且ListBox的选定元素绑定到一个元素

public static readonly DependencyProperty SelectedProgramProperty =
     DependencyProperty.Register("SelectedProgram", 
     typeof(ProgramData), typeof(ProgramView), 
                                                                                                                    new PropertyMetadata(default(ProgramData)));
    public DispenserInfo SelectedProgram
    {
        get { return (ProgramData)GetValue(SelectedProgramProperty); }
        set { SetValue(SelectedProgramProperty, value); }
    }

当用户更改ListBox中的选定元素时,我想检查“旧”选定元素的状态 - 也许我们需要保存旧元素 - 并以某种方式做出反应。

所以我想这样的事情

public static bool UpdateCallback(ProgramData oldVal, ProgramData newVal)
    {
        if (oldVal.DataChanged == false)
            return true;
        var res = MessageBox.Show("Save or discard changes", "Question",
                    MessageBoxButton.YesNoCancel, MessageBoxImage.Question);
        switch (res)
        {
            case MessageBoxResult.Yes: 
                oldVal.Save();
                return true;
            case MessageBoxResult.No:
                oldVal.Discard();
                return true;
            case MessageBoxResult.Cancel:
                return false;
        }
        return true;
    }

我有办法用验证/强制回调吗?

更新

正如Oliver和Sheridan建议我尝试了改变以及强制回调,这在单击和刷新UI之间执行某些任务非常有效。但是当我尝试取消coerceCallback中的更新时,就像这样

private static object CoerceValueCallback(DependencyObject dependencyObject, object baseValue)
    {
        var @this = (ProgramView)dependencyObject;
        var res = MessageBox.Show("Save or discard changes", "Question", MessageBoxButton.YesNoCancel, MessageBoxImage.Question);
        switch (res)
        {
            case MessageBoxResult.Cancel:
                return @this.SelectedProgram;
        }
        return baseValue;
    }

UI按预期保持旧值,但ListBox突出显示错误的行 - 用户单击的行,而不是在coerceCallback中取消时绑定的行。 我需要手动更新绑定吗?任何想法

2 个答案:

答案 0 :(得分:1)

您可以向PropertyChanged添加DependencyProperty处理程序:

public static readonly DependencyProperty ProgramsProperty =
       DependencyProperty.Register("Programs",
       typeof(ObservableCollection<ProgramData>), typeof(ProgramView),
       new UIPropertyMetadata(default(ObservableCollection<ProgramData>, 
       (d, e) => ((ProgramView)d).OnProgramsChanged(d, e))));

private void OnProgramsChanged(DependencyObject dependencyObject, 
    DependencyPropertyChangedEventArgs e)
{
    // Do something with e.OldValue and e.NewValue here
}

答案 1 :(得分:0)

当然有。查看DependencyProperty.Register的最后一个参数!

    public static readonly DependencyProperty MyPropertyProperty =
        System.Windows.DependencyProperty.Register("MyProperty", typeof(string), typeof(MyClass), new PropertyMetadata(default(string), (
            sender, args) =>
        {
            //changed callback
                var @this = (MyClass)sender;
                var newval = (string)args.NewValue;
                var oldval = (string)args.NewValue;
                // do whatever you like
            },
            (s, e) =>
                {
                    // coerce callback
                    if (e == null)
                        return " - empty string -";
                    return e;
                }));

对于大多数WPF依赖项属性,还有更多:属性元数据是FrameworkPropertyMetadata的实例,而不是简单的旧的PropertyMetadata。它有更多“隐藏”选项。您也可以使用它而不是PropertyMetadata。