【问题标题】:Binding to (possibly) null property in code not updating ModelView在不更新 ModelView 的代码中绑定到(可能)null 属性
【发布时间】:2014-11-20 18:42:35
【问题描述】:

我绑定了一个如下所示的 Singleton 属性:

<ComboBox ItemsSource="{Binding SourceList, UpdateSourceTrigger=PropertyChanged}" 
                                      SelectedItem="{Binding Source={x:Static local:MySingleton.Instance}, UpdateSourceTrigger=PropertyChanged, 
                                      Path=PossibleNullProperty.PossibleNullProperty.PossibleNullProperty.Source}" 
                                      Width="Auto" />

这很好用,即使 PossibleNullProperty 为 null,只要它们发生变化,'Source' 属性就会绑定到 ComboBox。

现在我的 ModelView 中还有一个命令绑定,它绑定到 ViewModel 中的 DelegateCommand。一旦 SelectedItem 发生更改,DelegateCommand 应该引发 CanExecuteChangedEvent。

好吧,我不能在“源”属性所在的对象中引发此事件。 所以我必须在 ViewModel 中引发这个事件。 我的想法是创建一个指向嵌套属性的属性,如下所示:

public string Source
    {
        get { return MySingleton.Instance.PossibleNullProperty?.PossibleNullProperty?.PossibleNullProperty?.Source; }
        set
        {
            MySingleton.Instance.PossibleNullProperty.PossibleNullProperty.PossibleNullProperty.Source = value;
            RaisePropertyChanged();
            MyCommand.RaiseCanExecuteChanged();
        }
    }

现在的问题是,在发生绑定时,链中的属性为空,因此 ComboBox SelectedItem 无法“到达”“源”属性。 在应用程序运行时,这可能会发生变化,并且“源”属性是“可访问的”,但 ModelView 不会更新。

如何解决我的问题?

谢谢

【问题讨论】:

  • 将视图所需的所有数据放入视图模型(或隐藏代码)中。
  • 但是如果嵌套属性发生变化怎么办,所以我必须在整个链中订阅PropertyChanged事件,当属性发生变化时,我必须在我的ViewModel中设置新值......跨度>
  • 在最简单的方法中,您必须确保属性链中的每个类型都实现 INotifyPropertyChanged 并将 MySingleton 作为属性公开在您的 VM 上,而绑定路径将是从 MySingleton 到所需的整个路径财产。否则,您将以某种方式收听每个属性的通知。
  • 整个链中的每个对象都实现了 INotifyPropertyChanged,但是“将 MySingleton 公开为 VM 上的属性”是什么意思?

标签: c# wpf xaml binding


【解决方案1】:

在你的 ViewModel 中添加这个,你会做得很好:

    CommandManager.RequerySuggested += CommandManager_RequerySuggested;

    private void CommandManager_RequerySuggested(object sender, EventArgs e)
    {
        this.MyCommand.CanExecute = "..." 
    }

每次 UI 更改都会调用 CommandManager_RequerySuggested!!!!

由于此事件是静态的,它只会将处理程序作为弱引用保存。

别忘了使用 async/await :)

【讨论】:

  • 嗨,这部分解决了我的问题,CanExecuteChangedEvent 将被调用,但绑定没有更新,我做错了什么?
  • 您询问了如何从 ViewModel 触发 CanExecute。就是这样 :) 如果您希望绑定知道静态属性何时更改,我建议您看看如何正确绑定到静态属性。 jonathanantoine.com/2011/09/28/…
  • 没关系,解决方案有效,我只需要删除指向嵌套属性的属性并再次直接绑定到单例。感谢您的解决方案!
【解决方案2】:

对于有同样问题的人,这就是我的 DelegateCommand 类现在的样子,它完美地工作,感谢开发刺猬的解决方案!

public class DelegateCommand<T> : System.Windows.Input.ICommand where T : class
{
    private readonly Predicate<T> _canExecute;
    private readonly Action<T> _execute;

    public DelegateCommand(Action<T> execute)
        : this(execute, null)
    {
    }

    public DelegateCommand(Action<T> execute, Predicate<T> canExecute)
    {
        _execute = execute;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        if (_canExecute == null)
            return true;

        return _canExecute((T)parameter);
    }

    public void Execute(object parameter)
    {
        _execute((T)parameter);
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-27
    • 2013-01-31
    • 2012-08-12
    • 1970-01-01
    • 2021-04-02
    • 1970-01-01
    • 2023-03-17
    • 2018-07-27
    相关资源
    最近更新 更多