Какие подходы доступны для фиктивных данных времени разработки в WPF?

Я работаю без смешивания выражений и просто использую редактор XAML в vs2010. Помимо этого, я все чаще вижу необходимость привязки данных во время разработки. Для простых случаев FallbackValue свойство работает очень хорошо (Textboxes и TextBlocks, и т. д.). Но особенно когда имеешь дело с ItemsControl и тому подобному, на самом деле нужны образцы данных, которые будут видны в конструкторе, чтобы вы могли настраивать и настраивать элементы управления и шаблоны данных без необходимости запуска исполняемого файла.

я знаю это ObjectDataProvider допускает привязку к типу и, таким образом, может предоставлять данные времени разработки для визуализации, но затем возникает некоторая хитрость, позволяющая связывать реальные данные времени выполнения, не тратя ресурсы, загружая загрузку как времени разработки, фиктивных данных и привязки времени выполнения.

На самом деле я хочу, чтобы, скажем, "Джон", "Пол", "Джордж" и "Ринго" отображались в конструкторе XAML в качестве элементов, которые можно стилизовать в моем ItemsControl, но реальные данные отображаются при запуске приложения.

Я также знаю, что Blend допускает некоторые причудливые атрибуты, которые определяют данные привязки времени разработки, которые эффективно игнорируются WPF в условиях времени выполнения.

Итак, мои вопросы:

1. Как можно использовать привязки коллекций и нетривиальных данных во время разработки в конструкторе XAML для Visual Studio, а затем плавно переключаться на привязки времени выполнения?

2. Как другие решили эту проблему данных времени разработки и времени выполнения? В моем случае я не могу очень легко использовать одни и те же данные для обоих (как можно было бы, скажем, с запросом к базе данных).

3. Могут ли их альтернативы выражению blend использовать для разработки XAML с интеграцией данных? (Я знаю, что есть некоторые альтернативы, но я определенно хочу что-то, что я могу использовать и увидеть связанные образцы данных и т. Д.?)

8 ответов

Решение

Используя VS2010, вы можете использовать атрибуты времени разработки (работает как для SL, так и для WPF). В любом случае у меня обычно есть фиктивный источник данных, так что это всего лишь вопрос:

  • Добавление объявления пространства имен

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    
  • Добавление контекста фиктивных данных в оконные / управляющие ресурсы

    <UserControl.Resources>
      <ViewModels:MockXViewModel x:Key="DesignViewModel"/>
    </UserControl.Resources>
    
  • Настройка контекста данных времени разработки

    <Grid d:DataContext="{Binding Source={StaticResource DesignViewModel}}" ...
    

Работает достаточно хорошо.

Как смесь принятого ответа Горана и превосходного комментария Рене.

  • Добавьте объявление пространства имен.xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

  • Ссылка на ваш контекст данных времени проектирования из кода.
    <Grid d:DataContext="{d:DesignInstance Type=ViewModels:MockXViewModel, IsDesignTimeCreatable=True}" ...

Я использую этот подход для генерации данных времени разработки в.NET 4.5 и Visual Studio 2013.

У меня есть только одна ViewModel. Модель представления имеет свойство IsInDesignMode который говорит, активен ли режим дизайна (см. класс ViewModelBase). Затем вы можете настроить данные времени разработки (например, заполнение элемента управления) в конструкторе моделей представлений.

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

public abstract class ViewModelBase
{
    public bool IsInDesignMode
    {
        get
        {
            return DesignerProperties.GetIsInDesignMode(new DependencyObject());
        }
    }
}

public class ExampleViewModel : ViewModelBase
{
    public ExampleViewModel()
    {
        if (IsInDesignMode == true)
        {
            LoadDesignTimeData();
        }
    }

    private void LoadDesignTimeData()
    {
        // Load design time data here
    }       
}

Карл Шиффлетт описывает подход, который должен одинаково хорошо работать для VS2008 и VS2010:

Просмотр данных времени разработки в Visual Studio 2008 Cider Designer в проектах WPF и Silverlight

У Лорана Бюньона есть похожий подход, который фокусируется на Expression Blend. Это может работать для VS2010, но я еще не подтвердил это.

Имитация данных в режиме разработки в Microsoft Expression Blend

Подобно ответу с самым высоким рейтингом, но, на мой взгляд, лучше: вы можете создать статическое свойство, чтобы возвращать экземпляр проектных данных и ссылаться на него непосредственно из XAML, например, так:

<d:UserControl.DataContext>
    <Binding Source="{x:Static designTimeNamespace:DesignTimeViewModels.MyViewModel}" />
</d:UserControl.DataContext>

Это избавляет от необходимости использовать UserControl.Resources, Ваше статическое свойство может функционировать как фабрика, позволяющая вам создавать нетривиальные типы данных - например, если у вас нет ctor по умолчанию, вы можете вызвать фабрику или контейнер здесь для внедрения в соответствующие зависимости.

Может быть, вам подойдут новые функции времени разработки Visual Studio 2010 и Expression Blend 4.

Как это работает, показано в примере приложения BookLibrary WPF Application Framework (WAF). Пожалуйста, загрузите версию.NET4.

Используя Visual Studio 2017, я пытался следовать всем руководствам и вопросам, таким как этот, и я все еще сталкивался с <ItemsControl> который просто не выполнял код, который у меня был внутри конструктора DesignFooViewModel который наследует от FooViewModel, Я подтвердил, что часть "не выполнена", следуя этому "удобному" руководству MSDN (спойлер: MessageBox отладка). Хотя это не имеет прямого отношения к первоначальному вопросу, я надеюсь, что это сэкономит много времени другим.

Оказывается, я не делал ничего плохого. Проблема заключалась в том, что мое приложение должно быть построено для x64. Поскольку Visual Studio все еще в 2018 году является 32-битным процессом и, очевидно, не может вращать 64-битный хост-процесс для конструктора, он не может использовать мои классы x64. Плохо то, что в любом журнале я не могу найти никаких ошибок.

Так что, если вы наткнулись на этот вопрос, потому что вы видите фиктивные данные в вашей модели представления времени разработки (например: <TextBlock Text="{Binding Name}"/> появляется Name независимо от того, установлено ли для свойства значение), скорее всего, это будет ваша сборка x64. Если вы не можете изменить конфигурацию сборки на anycpu или x86 из-за зависимостей, рассмотрите возможность создания нового проекта, который будет полностью anycpu и не будет иметь зависимостей (или каких-либо зависимостей). Таким образом, вы заканчиваете тем, что разделяете большую часть или все части кода, кроме частей инициализации, из вашего проекта "WPF App" в проект "Библиотека классов C#".

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

Мне понравилось предложение jbe, в частности, чтобы посмотреть, как они это делают в примерах приложений платформы WAF - они используют отдельные модели представления mock/sample в папку, а затем иметь такую ​​​​строку в XAML:

      mc:Ignorable="d" 
d:DataContext="{d:DesignInstance dd:MockHomeViewModel, IsDesignTimeCreatable=True}"

(куда указывает на пространство имен, где жизни)

Это красиво и просто (что мне нравится!), и вы можете наследовать от реальных виртуальных машин и просто предоставлять фиктивные данные. Это разделяет вещи, так как вам не нужно загрязнять ваши настоящие виртуальные машины каким-либо кодом, предназначенным только для времени разработки. Я понимаю, что для большого проекта, использующего IOC и т. д., все может выглядеть совсем иначе, но для небольших проектов это работает хорошо.

Но, как указал joonas, кажется, что он не работает со сборками x64 в VS2017, и это все еще похоже на VS2019 (я использую версию сообщества V2019 16.6). С самого начала начать работать несложно, но это может вызвать некоторую головную боль, когда после внесения изменения (или, как обычно бывает, нескольких изменений!) он внезапно перестает работать.

Всем, кто пытается это сделать, я бы порекомендовал создать новый простой проект WPF (скажем, одно представление, одну модель представления, одну фиктивную виртуальную машину) и поэкспериментировать с ним; заставить его работать, а затем сломать его. Иногда я обнаруживал, что никакие очистки и перестроения решения не могли исправить это, единственное, что работало, — это закрытие VS и перезапуск, и внезапно мои данные времени проектирования возвращались!

Другие вопросы по тегам