Как я могу заставить свой UserControl выглядеть как ComboBox? - PullRequest
2 голосов
/ 15 февраля 2011

У меня есть пользовательский элемент управления, содержащий TextBox, ToggleButton и Popup, как настоящий ComboBox. Теперь моя проблема - сделать так, чтобы он выглядел так же, как обычный ComboBox.

В Blend я могу «Редактировать шаблон / Редактировать копию ...» реального ComboBox, чтобы получить нужные кусочки, чтобы он выглядел правильно. Для одной темы Windows (Aero). Если приложение запущено на другой теме (например, Luna), элемент управления не меняет свой внешний вид, он по-прежнему имеет внешний вид Aero.

Нужно ли указывать стиль / шаблон для каждой темы Windows или я могу каким-то образом овладеть (во время выполнения) стилем ComboBox по умолчанию и применить его к своему UserControl?

Вместо создания UserControl я попытался изменить настоящий ComboBox под свои нужды, но я просто не мог заставить его работать. Как я могу заменить ВСЕ логику ComboBox своей собственной?

1 Ответ

1 голос
/ 20 марта 2011

Использование преимуществ тем Windows было бы одним из способов решения этой проблемы.Большая часть этого перефразирована и усечена из Windows Presentation Foundation, развернутого Адамом Натаном.

Простой подход

Вы можете использовать открытые ресурсы и ключина SystemColors, SystemFonts и SystemParameters в вашем шаблоне управления (вместе с DynamicResource, если тема изменяется во время работы вашей программы), чтобы установить соответствующие значения:

Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"

Надежный подход

Лучший способ, хотя он требует больше работы, - это иметь шаблон элемента управления для каждой темы, а не один набор, который переопределяет все.Для этого вы должны поместить все ресурсы, относящиеся к вашей теме, в собственный словарь ресурсов.Эти словари находятся в подпапке themes в корне вашего проекта, и каждый из них назван в честь названия темы и цвета темы: ThemeName.ThemeColor.xaml.

Обратите внимание, что вы все еще используетеSystemColors, SystemFonts и SystemParameters, как в простом подходе.

У меня нет более новой редакции книги, в которой, вероятно, перечислены темы Windows 7, но вот список Адамав издании у меня есть:

  • Vista Aero: themes \ Aero.NormalColor.xaml
  • XP по умолчанию: themes \ Luna.NormalColor.xaml
  • XP зеленый:themes \ Luna.Homestead.xaml
  • XP silver: themes \ Luna.Metallic.xaml
  • XP royale: themes \ Royale.NormalColor.xaml
  • XP Zune: темы \Zune.NormalColor.xaml
  • Classic: themes \ Classic.xaml

Они будут автоматически загружены и отключены при смене темы.Вы также можете указать themes \ Generic.xaml по умолчанию, когда он пытается загрузить тему, которой не соответствует созданный словарь ресурсов.

Вы также должны включить автоматическое создание тем с помощьюThemeInfoAttribute:

//look inside this assembly
[assembly:ThemeInfo(ResourceDictionaryLocation.SourceAssembly, 
    ResourceDictionaryLocation.SourceAssembly)]

ResourceDictionaryLocation также имеет опцию ExternalAssembly.Соглашение об именах для этих внешних сборок - MainAssembly.ThemeName.dll, поэтому, если ваша сборка называется MyApp, она будет искать словарь ресурсов классической темы в MyApp.Classic.dll.

И, наконец, вы используете ThemeDictionaryExtension в словаре ресурсов вашего приложения:

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="{ThemeDictionary MyApp}"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

Если вы создаете какие-либо пользовательские элементы управления, производные от другого элемента управления (например, не UserControl, а ProgressBar), вы должны сделать это в его статическомконструктор:

DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl),
    new FrameworkPropertyMetadata(typeof(MyControl)));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...