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

97

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

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

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

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

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

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

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

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

el2iot2
источник

Ответы:

120

Используя 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}}" ...

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

Горан
источник
2
Если у вас возникли проблемы с использованием, d:DataContextвы можете найти помощь в этом вопросе: stackoverflow.com/questions/8303803/…
Martin Liversage
27
Не приведет ли этот пример к загрузке экземпляра MockXViewModel в ваши ресурсы для сборки выпуска? Разве это не проблема?
jpierson 05
12
К вашему сведению: вам также понадобится следующее, иначе компилятор VS2012 не скомпилирует xaml-файл: xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"иmc:Ignorable="d"
Орион Эдвардс
51
Джеперсон прав. Я предпочитаю использовать <Grid d:DataContext="{d:DesignInstance Type=ViewModels:MockXViewModel, IsDesignTimeCreatable=True}" .... Таким образом, имитируемая модель просмотра будет создана только в дизайнере, а не во время работы вашего приложения. Имейте в виду, что этот подход требует, чтобы ваша модель фиктивного представления имела конструктор без параметров. Но то же самое и в примере, приведенном выше в ответе.
René
2
@ Рене, твой подход намного лучше. Пожалуйста, добавьте это как ответ, и я проголосую за него
dss539
15

Как сочетание принятого ответа Горана и отличного комментария Рене.

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

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

Джон Стритенбергер
источник
1
У меня есть соблазн отметить это как новый ответ, но, возможно, мы сможем включить остальные детали.
el2iot2 03
Это требует большей наглядности, или это нужно включить в принятый ответ. Это гораздо лучшее решение.
Lauraducky
Почему так лучше? Сначала я подумал, что принятый ответ излишне создаст фиктивные модели также во время выполнения, но я тестировал это, и на самом деле это не так. Ресурсы не создаются, если не используются.
Пол
@Paul Это действительно вопрос предпочтений, но этот ответ сохраняет весь контекст данных времени разработки в одном объявлении, а не в двух местах. Облегчает изменения
Джон Стритенбергер
1
@JohnStritenberger Это не просто предпочтение, принятый ответ излишне загружает ресурсы в память навсегда, а не только для дизайнера.
UuDdLrLrSs
4

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

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

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

Моделирование данных в режиме разработки в Microsoft Expression Blend

dthrasher
источник
спасибо, что обратил на это мое внимание. Мне нравится концепция DesignAndRunTimeDataContext.
el2iot2
1
У Карла Шиффлетта есть обновленная статья для Visual Studio 2010: Примеры данных в WPF и Silverlight Designer
totorocat
1
Суть содержания ссылки действительно следует отредактировать в ответ, тем более что первая ссылка теперь мертва.
Lauraducky
4

Возможно, вам подойдут новые возможности Visual Studio 2010 и Expression Blend 4 во время разработки.

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

jbe
источник
Спасибо за ссылку. Есть ли конкретный файл кода или конструкция, на которые мне следует обратить внимание, чтобы увидеть подход? (краткий обзор было бы здорово)
el2iot2
Взгляните на проект BookLibrary.Presentation. В этом проекте вы найдете папку «DesignData», которая используется UserControls в папке «Views».
jbe
1
+1. Просто взглянул на это. Для всех, кто интересуется, образец модели представления данных объявлен в XAML и на него ссылаются через d: DataContext = "{d: DesignData Source = .. / DesignData / SampleLendToViewModel.xaml}"
RichardOD
4

Я использую этот подход для создания данных времени разработки с помощью .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
    }       
}
Мартин
источник
4

Используя 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» в проект «Библиотека классов C #».

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

Joonas
источник
3

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

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

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

Джек Уклея
источник