0

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

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); }
    }

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

所以我想要这样的东西

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 中取消时绑定的行。我需要手动更新绑定吗?有任何想法吗

4

2 回答 2

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
}
于 2013-11-06T09:04:40.490 回答
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。

于 2013-11-06T09:06:03.927 回答