2016-07-14 56 views
2

首先,我知道这是最重复的问题之一,需要询问...我将节省你有一段时间说这是一个转折点。对象引用未设置为WPF设计器中对象的实例,位于x处:参考

首先,设置

<UserControl {d:DesignInstance Type=MyControl, IsDesignTimeCreatable=True}> 
    <Grid x:Name="root"> 
     <FrameElement x:Name="ContextProxy" Visibility="Collapsed" /> 
     ... 
     <DataGridTextColumn.Visibility> 
      <!-- squiggly line on the SOURCE part --> 
      <Binding Source="{x:Reference Name=ContextProxy}" 
        Path=DataContext.IncludeThisColumn 
        /> 
     </DataGridTextColumn.Visibility> 
    </Grid> 
</UserControl> 

代码隐藏

public partial class MyControl { 

    // viewmodel for INPC (data lookups, child controls, etc) 
    public ViewModels.vmMyControl { get; } = new ViewModels.vmMyControl(); 

    MyControl() { // ctor 
     this.root.DataContext = this; // to support DependencyProperty 
    } 

    // several dependency properties for external use/bindings 
    public static DP IncludeThisColumnDP = DP.Register(..., OnIncludeThisColumnChanged) 
    public bool IncludeThisColumn { GetValue(DP); } { SetValue(DP, value); } 

    // relay DP changes from parent/outside world, to internal ViewModel 
    private void OnIncludeThisColumnChanged(..) 
    { (o as vmMyControl).ViewModel.IncludeThisColumn = e.NewValue; } 
} 

视图模型

public class vmMyControl { 

    private readonly myObservableINPC<bool> _IncludeThisColumn; 
    public bool IncludeThisColumn { get/set for _IncludeThisColumn.Value } 

    public vmMyControl() { // ctor 
     // initialize INPC crap 
     this.IncludeThisColumn = new blah(nameof(IncludeThisColumn)); 

     // data for designer 
     if (...GetIsInDesignMode) 
      Data_LoadMock(); 
    } 

    public Data_LoadMock() { 
     // populate some of the data points 
    } 
} 

所以一般来讲,我觉得我以下最佳实践(比其他混合DP/INPC,但它很好地满足了我的需求,那么是什么曾经)...

  • 用户控件的数据上下文被施加到内部根元素(顶级网格)

  • 数据上下文设置为用户控件以启用DP的实例。

  • 用户控件实例都有初始化为视图模型只读属性

  • 视图模型使用GetIsInDesignMode,以确保数据不会加载(实际上,代码的DAL代理还检查内部布尔指示时,他们正在运行作为一个单元测试,以进一步确认他们被禁用,与InternalsVisibleTo(UnitTestProject))

  • 因为datagrid列的可见性不能直接绑定(不是在元素树或任何),我添加了一个FrameworkElement作为datacontext的代理


扭转

所以,首先让我说,在运行时,代码工作。所有的绑定,数据加载等都没有例外。这纯粹是一个设计时问题,但它让我感到困惑。

因为我处理瓦特/ WPF设计模式时,所知道的空引用的问题,我的第一个动作,当我看到这个问题是添加:

MyControlTests.cs

[TestMethod] 
public void InstantiateVM() { 
    Action a =() => { return new vmMyControl(); } 
    a.ShouldNotThrow(); // FluentAssertions 
} 

[TestMethod] 
public void InstantiateUC() { 
    Action a =() => { return new MyControl(); } 
    a.ShouldNotThrow(); // FluentAssertions 
} 

这里的事情......两个测试都成功运行......并且在检查(调试+断点)时,对象中的任何属性都不会导致异常。


环境

应用程序使用的框架4.5和C#6(因为我在VS2015)

我看到有人张贴关于VS2015悬停在消息获得更多的信息,但它似乎没有为我做任何事情。

为什么它的价值,我使用VS2015 REL ...试图应用更新2或3,但似乎有一些错误,从我听到/阅读的东西。

+0

也,我已经证实,GetIsInDesignMode不加入一个早期的回归问题; “在构造函数中(在用户控件中,它立即跟着InitializeComponents调用) –

+0

我开始怀疑设计器中是否还有其他东西需要包含在我的单元测试中......初始化中涉及到的东西或其他东西? (我不覆盖任何控件的成员) –

+0

这是一个已知的VS bug,已经存在很久了。它无法正确处理'x:Reference'。解决此问题时尽可能使用带'ElementName ='的绑定。 –

回答

0

http://www.thomaslevesque.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-inherited/

public class BindingProxy : Freezable 
{ 
#region Overrides of Freezable 

protected override Freezable CreateInstanceCore() 
{ 
    return new BindingProxy(); 
} 

#endregion 

public object Data 
{ 
    get { return (object)GetValue(DataProperty); } 
    set { SetValue(DataProperty, value); } 
} 

// Using a DependencyProperty as the backing store for Data. This enables animation, styling, binding, etc... 
public static readonly DependencyProperty DataProperty = 
    DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null)); 
} 

然后

<DataGrid.Resources> 
    <local:BindingProxy x:Key="proxy" Data="{Binding}" /> 
</DataGrid.Resources> 

<DataGridTemplateColumn.Visibility> 
    <Binding Source="{StaticResource ResourceKey=DataContextProxy}" 
      Path="Data.IncludeThisColumn" 
      Converter="{StaticResource ResourceKey=BoolToHiddenConverter}" 
      /> 
</DataGridTemplateColumn.Visibility> 
相关问题