Динамические ресурсы уровня приложения не являются динамическими, если они размещены в ElementHost.

StackOverflow https://stackoverflow.com/questions/727141

Вопрос

Я размещаю пользовательский элемент управления WPF в контейнере WinForms.Теперь я хочу иметь возможность использовать тему/оболочку UserControl.Для этого у меня есть несколько ресурсных словарей, которые определяют «шкуры». Когда мое приложение запускается, я создаю «New System.windows.application ()», чтобы это приложение.Чтобы изменить тему, старый скин удаляется, а новый скин добавляется в словарь ресурсов уровня приложения во время выполнения.Однако это не меняет ни один из ресурсов с динамическими ссылками в 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)));

   ...
}

Теперь, когда нажата кнопка «Белый», я ожидаю, что кнопка в UserControl станет белой, а при нажатии кнопки «Черный» я ожидаю, что кнопка станет черной.Однако этого не происходит.

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

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

Спасибо, пыльный

Это было полезно?

Решение

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

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

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

Другие советы

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top