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, поэтому я теряю интеллект и получаю сообщения типа «Не удается разрешить свойство 'xxx' в контексте данных типа 'FooViewModelMock '".

Конечно, я мог бы установить контекст данных в DataGrid:

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

Это возвращает мне мой интеллект, но я теряю фиктивные данные.

Есть ли способ заставить контекст данных времени разработки распространяться через привязку ItemsSource и сохранять данные как intellisense, так и представления дизайна?

Спасибо


person Taran    schedule 02.09.2014    source источник


Ответы (1)


Насколько мне известно, это недостаток Visual Studio. Вот как я обхожу это.

Прежде всего, я не использую DesignInstance, так как не могу заставить его работать в Visual Studio 2013. Вместо этого я использую это:

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

Example — это статическое свойство, которое создает экземпляр класса ...DesignerData. Я понятия не имею, почему это работает, но DesignInstance, который должен делать то же самое, не работает. Я пытался указать IsDesignTimeCreatable, но это не помогло.

Этот класс должен иметь требуемое свойство коллекции, которое в моем случае возвращает только данные в виде анонимно типизированных объектов:

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

Однако обратите внимание, что это сделано только для того, чтобы избежать предупреждений и для автозаполнения. Их никогда не будут читать.

Большой потенциальный недостаток этого подхода заключается в том, что его нельзя использовать, если элементы одной коллекции имеют свойство с тем же именем, но с другим типом, чем в другой коллекции.

Это также неуклюже и неудобно, поскольку обходные пути обычно бывают.

person Anonymous Coward    schedule 16.09.2014