Які підходи доступні для фіктивних даних про час проектування у WPF?


97

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

Я знаю, що ObjectDataProviderдозволяє прив’язати до типу і, таким чином, може надати дані про час проектування для візуалізації, але тоді є деякий жонглювання, щоб дозволити прив'язування реальних даних про час, не витрачаючи ресурсів, завантажуючи завантаження обох проектних часів, дамміровані дані та прив'язки часу виконання.

Дійсно, чого я хочу - це можливість, скажімо, "Джон", "Пол", "Джордж" та "Рінго", в дизайнері XAML з'являються як стильові елементи в моєму ItemsControl, але реальні дані з'являються при застосуванні пробіжки.

Я також знаю, що Blend допускає деякі фантазійні атрибути, що визначають дані про прив'язку часу проектування, які ефективно ігноруються WPF в умовах виконання.

Отже, мої запитання:

1. Як я можу використовувати дизайнерські прив'язки колекцій та нетривіальних даних у візуальному дизайнері XAML, а потім плавно змінювати прив’язки до виконання?

2. Як інші вирішили цю проблему даних щодо проекту та часу виконання? У моєму випадку я не можу дуже легко використовувати однакові дані для обох (як можна було б сказати, наприклад, із запитом до бази даних).

3. Чи є їхніми альтернативами поєднання виразів, які я міг би використовувати для інтегрованого даних XAML-дизайну? (Я знаю, що є деякі альтернативи, але я конкретно хочу щось, що я можу використовувати і бачити зв'язані вибіркові дані тощо?)

Відповіді:


120

За допомогою VS2010 ви можете використовувати атрибути Design-Time (працює як для 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

12
FYI: Вам також потрібно наступне, інакше компілятор VS2012 не збиратиме файл xaml: xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"іmc:Ignorable="d"
Orion Edwards

51
jpierson має рацію. Я вважаю за краще використовувати <Grid d:DataContext="{d:DesignInstance Type=ViewModels:MockXViewModel, IsDesignTimeCreatable=True}" .... Таким чином, глузливий модельний вигляд буде створений лише в дизайнері, а не під час запуску вашої програми. Майте на увазі, що такий підхід вимагає, щоб ваша модель макетного перегляду мала конструктор без параметрів. Але те саме відбувається у прикладі, наведеному вище у відповіді.
Рене

2
@ Рене ваш підхід набагато кращий. Будь ласка, додайте його як відповідь, і я проголосую за нього
dss539

15

Як поєднання прийнятої відповіді Горана та відмінного коментаря Рене.

  • Додайте декларацію простору імен. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

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


1
Я спокушаюсь відзначити це новою відповіддю, але, можливо, ми можемо використати решту деталей.
el2iot2

Це потребує більшої наочності, або його потрібно втягнути у прийняту відповідь. Це набагато краще рішення.
Лорадукі

Чому це краще? Спочатку я думав, що прийнята відповідь зайво спричинить макетні моделі також під час виконання, але я перевірив це, а насправді це не так. Ресурси не створюються, якщо не використовуються.
Павло

@Paul Це дійсно питання переваги, але ця відповідь утримує весь контекст даних про час проектування в одній декларації проти наявності в двох місцях. Полегшує зміни
Джон Стрітенбергер

1
@JohnStritenberger Його не просто вподобання, прийнята відповідь зайво завантажує ресурси в пам’ять на весь час, а не лише для дизайнера.
UuDdLrLrSs

4

Карл Шиффлет описує підхід, який повинен працювати однаково добре для VS2008 та VS2010:

Перегляд даних про час дизайну в Cider Designer Visual Studio 2008 в проектах WPF та Silverlight

Лоран Буньйон має подібний підхід, який зосереджується на суміші Expression. Це може працювати для VS2010, але я цього ще не підтвердив.

Моделювання даних у режимі дизайну за допомогою Microsoft Expression Blend


дякую, що донесли це до моєї уваги. Мені подобається концепція DesignAndRunTimeDataContext.
el2iot2

1
Карл Шиффлет має оновлену статтю для Visual Studio 2010: Зразки даних у WPF та Silverlight Designer
totorocat

1
Суть вмісту посилання дійсно повинна бути відредагована у відповідь, тим більше, що перша посилання тепер мертва.
Лорадукі

4

Можливо, нові функції дизайну для Visual Studio 2010 та Expression Blend 4 - це час для вас.

Як це працює, показано у зразковому застосуванні BookLibrary програми WPF Application Framework (WAF) . Завантажте версію .NET4


Дякуємо за посилання. Чи є певний файл коду чи конструкція, яку я повинен роздивитись, щоб побачити підхід? (короткий огляд був би чудовим)
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 App" на проект "Бібліотека класів C #".

Що стосується кодової бази, над якою я працюю, я думаю, що це змусить здорово розділити проблеми за рахунок певного дублювання коду, що, мабуть, є чистим позитивним моментом.


3

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

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

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.