Динамические ресурсы уровня приложения не являются динамическими при размещении в ElementHost - PullRequest
5 голосов
/ 07 апреля 2009

Я размещаю WPF UserControl в контейнере WinForms. Теперь я хочу иметь возможность обрабатывать темы / обложки UserControl. Для этого у меня есть несколько ресурсных словарей, которые определяют «скины». Когда мое приложение запускается, я создаю «новый System.Windows.Application ()», чтобы существовал Application.Current. Для изменения темы старый скин удаляется, а новый скин объединяется со словарем ресурсов уровня приложения во время выполнения. Тем не менее, это не меняет ни один из ресурсов, на которые ссылаются в динамическом ключе в UserControl. Я попробовал это в прямом приложении WPF, и он работал просто отлично. Я что-то упустил или это вообще невозможно сделать? Кстати, если я добавлю скин в ресурсы приложения до инициализации UserControl, он будет работать, но я не смогу изменить скин после этого.

Чтобы сделать это самым простым способом:

Создайте новое приложение WinForms. Добавьте WPF UserControl в приложение. Это достаточно просто:

<UserControl ...>
   <Grid>
      <Button
         Background="{DynamicResource ButtonBG}"/>
   </Grid>
</UserControl>

Создайте два ResourceDictionaries, White.xaml и Black.xaml (или любой другой), которые имеют SolidColorBrush с ключом ButtonBG соответствующего цвета. В Form1.cs добавьте две кнопки и ElementHost. Установите дочерний элемент ElementHost для экземпляра UserControl, который мы только что создали. Подключите кнопки к событиям, которые меняют скин:

private void White_Click(object sender, EventArgs e)
{
   Application.Current.Resources.MergedDictionaries[0] = 
      (ResourceDictionary)Application.LoadComponent(
         new Uri(@"\WpfThemes;component\White.xaml", UriKind.Relative)));
}

private void Black_Click(object sender, EventArgs e)
{
   Application.Current.Resources.MergedDictionaries[0] = 
      (ResourceDictionary)Application.LoadComponent(
         new Uri(@"\WpfThemes;component\Black.xaml", UriKind.Relative)));
}

В Program.cs убедитесь, что Application.Current существует, и задайте начальный скин:

[STAThread]
static void Main()
{
   new System.Windows.Application();

   Application.Current.Resources.MergedDictionaries[0] =
      (ResourceDictionary)Application.LoadComponent(
         new Uri(@"\WpfThemes;component\White.xaml", UriKind.Relative)));

   ...
}

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

Кто-нибудь знает почему? Есть ли решение?

Редактировать: Идея: Возможно, если есть способ принудительно пересмотреть DynamicResources при изменении темы, это сработает.

Спасибо, Дасти

Ответы [ 2 ]

6 голосов
/ 01 мая 2009

Я думаю, что это может быть упущено из виду в рамках WPF.

Из того, что я могу сказать с помощью Reflector, видно, что когда словарь ресурсов Application катастрофически изменяется (изменение, которое, вероятно, будет иметь широкий спектр эффектов, таких как добавление, удаление или замена обложки), существует код, который зацикливается по всем Windows в приложении и заставляет их переоценить свои DynamicResources. Однако другие элементы, которые я бы рассмотрел верхнего уровня в WPF, такие как ElementHost s, не получают такой же обработки. Это приводит к тому поведению, которое я испытываю.

Мой обходной путь для решения этой проблемы - вручную просмотреть все мои ElementHost s и добавить, удалить или заменить файл скина ResourceDictionary. Это не идеально, но оно выполняет свою работу.

0 голосов
/ 24 июля 2014

Другим обходным решением будет создание фиктивного окна и указание содержимого элемента-элемента в качестве содержимого. Если вы загляните в приложение и проверите, как оно обрабатывает изменения в ресурсных словарях, вы увидите, что оно уведомляет только о окнах.

Единственное, что вы должны напомнить, это никогда не показывать окно (-> исключение) и закрывать его при утилизации elementhost, чтобы приложение могло корректно завершить работу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...