ItemsSource不传播设计时数据上下文

时间:2014-09-02 09:03:33

标签: c# wpf datagrid datacontext itemssource

我有一个包含一系列项目的视图模型:

public class FooViewModel
{
    public FooListItem[] ListItems { get; set; }
    ...
}

我创建了一个子类来充当设计时模拟,带有虚拟数据。

public class FooViewModelMock : FooViewModel
{
    public FooViewModelMock()
    {
        ListItems = <test data population...>
        ...
    }
}

然后我在窗口中连接模拟数据,工作正常。

<Window xmlns:mocks="clr-namespace:FooNS.Mocks"    
        xmlns:models="clr-namespace:FooNS.Model"     
        d:DataContext="{d:DesignInstance Type=mocks:FooViewModelMock, IsDesignTimeCreatable=True}"> ... 

然后在窗口中我有一个DataGrid并将ItemsSource绑定到视图模型上的属性:

<DataGrid ItemsSource="{Binding ListItems}"> ...

测试数据显示在设计窗口中很好,但问题是DataGrid的数据上下文仍然是FooViewModelMock,而不是FooListItem,所以我失去了智能感知并获得了诸如&#34;无法解析属性的消息。 XXX&#39;在类型&#39; FooViewModelMock&#39;&#34;的数据上下文中。

我当然可以在DataGrid中设置数据上下文:

d:DataContext="{d:DesignInstance models:FooListItem}"

这让我恢复了智能感知,但我丢失了模拟数据。

有没有办法让设计时数据上下文通过ItemsSource绑定向下传播,同时保留intellisense和设计视图数据?

由于

1 个答案:

答案 0 :(得分:4)

据我所知,这是Visual Studio中的一个缺陷。以下是我如何解决这个问题。

首先,我不使用DesignInstance,因为我无法在Visual Studio 2013中使用它。相反,我使用它:

d:DataContext="{x:Static userControls:[ insert class name here ]DesignerData.Example}"

示例是一个静态属性,用于创建... DesignerData类的实例。我不知道为什么会这样,但DesignInstance应该做同样的事情,并不是。我试图指定IsDesignTimeCreatable,但这没有帮助。

这个类必须具有所需的collection属性,在我的例子中,它只返回匿名类型对象形式的数据:

public IEnumerable<object> Elements
{
    get
    {
        return new object[]
        {
            new { ... },
            new { ... },
            new { ... }
        };
    }
}

在我的情况下,元素通常不能在没有其他应用程序运行的情况下轻松创建,因此使用这样的匿名类型对象可以避免元素中的大量代码让它们在设计时表现不同。

由于Visual Studio中存在缺陷,我们还必须具备元素的属性:

public string  Key   { get; private set; }
public Element Value { get; private set; }

但请注意,这只是为了避免警告和自动完成。这些将永远不会被阅读。

这种方法的一个很大的潜在缺点是,如果一个集合的元素具有同名但属性与另一个集合中的属性不同,则不能使用它。

它也很笨拙和不方便,因为常常会有变通方法。