在不更新ModelView的代码中绑定到(可能)null属性

时间:2014-11-20 08:36:56

标签: c# wpf xaml binding

我绑定了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中还有一个Command Binding,它绑定到ViewModel中的DelegateCommand。一旦SelectedItem发生更改,DelegateCommand就会引发CanExecuteChangedEvent。

好吧,我无法在'Source'属性所在的Object中引发此事件。 所以我必须在ViewModel中引发此事件。 我的想法是创建一个指向嵌套属性的属性,如下所示:

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

现在的问题是,在绑定发生时,链中的属性为null,因此ComboBox SelectedItem无法“到达”'Source'属性。 在Application Runtime期间,这可以更改,并且'Source'属性是“可访问的”,但ModelView不会更新。

如何为我的问题找到解决方案?

由于

2 个答案:

答案 0 :(得分:0)

在ViewModel中添加它,你会做得很好:

    CommandManager.RequerySuggested += CommandManager_RequerySuggested;

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

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

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

别忘了使用async / await:)

答案 1 :(得分:0)

对于有相同问题的人来说,这就是我的DelegateCommand类现在看起来的样子,并且它非常有效,感谢dev hedgehog的解决方案!

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