WPF表示数据项在非空时为空

时间:2012-07-31 20:13:30

标签: .net wpf xaml data-binding mvvm

我有一个与WPF和MVVM一起使用的ViewModel类:

public class ViewModel {

    /* Other members here... */

    public ReadOnlyObservableCollection<BackplaneViewModel> Backplanes {
        get { return _Backplanes; }
    }

    public BackplaneViewModel CurrentBackplane {
        get { 
            var cb = _CurrentBackplane ?? (_CurrentBackplane = Backplanes.First()); 
            return cb;
        }
        set { 
            if (_CurrentBackplane == value) return;
            _CurrentBackplane = value; 
            RaisePropertyChanged("CurrentBackplane");
        }
    }
}

_Backplanes集合在构造函数中创建并填充,永远不会更改。

我有一个控件使用此ViewModel的实例作为其DataContext。用户可以选择CurrentBackplane ComboBox

<ComboBox ItemsSource="{Binding Backplanes}"
          SelectedItem="{Binding CurrentBackplane}"
          DisplayMemberPath="BackplaneIndex" />

CurrentBackplane也可能会在代码中更改。

我在get的{​​{1}}上加了一个断点。 CurrentBackplane变量非空。但是,在cb请求其值后,我立即在输出窗口中获得以下内容:

WPF

为什么System.Windows.Data Information: 40 : BindingExpression path error: 'BackplaneIndex' property not found for 'object' because data item is null. This could happen because the data provider has not produced any data yet. BindingExpression:Path=BackplaneIndex; DataItem=null; target element is 'ComboBox' (Name=''); target property is 'NoTarget' (type 'Object') System.Windows.Data Information: 19 : BindingExpression cannot retrieve value due to missing information. BindingExpression:Path=BackplaneIndex; DataItem=null; target element is 'ComboBox' (Name=''); target property is 'NoTarget' (type 'Object') System.Windows.Data Information: 20 : BindingExpression cannot retrieve value from null data item. This could happen when binding is detached or when binding to a Nullable type that has no value. BindingExpression:Path=BackplaneIndex; DataItem=null; target element is 'ComboBox' (Name=''); target property is 'NoTarget' (type 'Object') System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=BackplaneIndex; DataItem=null; target element is 'ComboBox' (Name=''); target property is 'NoTarget' (type 'Object') 告诉我数据项为空?

我不确定我做错了什么。该程序实际运行正常,但我正在尝试追踪我认为可能与此问题相关的内存泄漏。

5 个答案:

答案 0 :(得分:0)

您是否尝试在构造函数中将集合的值设置为第一个值并将getter代码更改为仅返回_CurrentBackplane后设置_CurrentBackplane?

_CurrentBackplane = Backplanes.First();  

public BackplaneViewModel CurrentBackplane {  
    get {   
        return _CurrentBackplane;  
    }  
    set { _CurrentBackplane = value; }  
}  

答案 1 :(得分:0)

除了Joshs回答你应该在你的二传手中提高属性

set { _CurrentBackplane = value; OnPropertyChanged("CurrentBackplane "); }

你应该为你的SelectedItem将Mode设置为TwoWay

SelectedItem="{Binding CurrentBackplane, Mode=TwoWay}"

然后你得到一个绑定信息而不是绑定错误

答案 2 :(得分:0)

在将日志记录写入输出窗口之前,您是否可以检查DataContext是否已实际设置为ViewModel实例?您可以通过将事件处理程序连接到DataContextChanged事件来完成此操作。

我发现我的代码存在类似的问题,遗憾的是我还没有弄清楚如何防止它,但是如果我这样做的话,我会告诉你。

答案 3 :(得分:0)

我不确定这是不是答案,但试一试。在您的应用程序集中:

System.Diagnostics.PresentationTraceSources.DataBindingSource.Switch.Level = System.Diagnostics.SourceLevels.Critical;

这可能会解决问题。

答案 4 :(得分:0)

对我来说,解决方案是在重置DataContext属性后重新检查它,然后重置绑定:

var resolvedSource = bindingExpression.ResolvedSource;
if (resolvedSource == null)
{
  textBox.DataContextChanged += dataContextChanged;

  static void dataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
  {
    var frameworkElement = (FrameworkElement)sender;
    var be = frameworkElement.GetBindingExpression(TextBox.TextProperty);
    var newBe = BindingOperations.SetBinding(
      (DependencyObject)sender, TextBox.TextProperty, be.ParentBinding);
    Debug.Assert(newBe is BindingExpression);
    Debug.Assert(newBe.DataItem != null);

    //here newBe.DataItem should not be null
    addValidationRules((BindingExpression)newBe);
    frameworkElement.DataContextChanged -= dataContextChanged;
  }
  return;
}
addValidationRules(bindingExpression);