如何让我的UserControl看起来像ComboBox?

时间:2011-02-15 16:28:25

标签: wpf user-controls combobox themes

我有一个包含TextBox,ToggleButton和Popup的用户控件,就像真正的ComboBox一样。现在我的问题是设置样式,使它看起来就像普通的ComboBox。

在Blend中,我可以对一个真正的ComboBox进行“编辑模板/编辑副本...”,以获得让我看起来正确的点点滴滴。对于一个Windows主题(Aero)。如果应用程序在另一个主题(例如Luna)上运行,则控件不会改变其外观,它仍然具有Aero外观。

我是否必须为每个Windows主题提供样式/模板,或者我能否以某种方式获取(在运行时)默认的ComboBox样式并将其应用于我的UserControl?

我没有使用UserControl,而是尝试根据我的需要修改一个真正的ComboBox,但我无法让它工作。如何用我自己的逻辑替换ComboBox的所有逻辑?

1 个答案:

答案 0 :(得分:1)

利用Windows主题将是解决此问题的一种方法。其中大部分是由Adam Nathan从 Windows Presentation Foundation Unleashed 中解释和截断的。

简单方法

您可以使用控件模板中SystemColorsSystemFontsSystemParameters公开的资源和密钥(以及DynamicResource,以防更改主题时使用你的程序正在运行)来设置适当的值:

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

强有力的方法

更好的方法,虽然它需要更多的工作,但是每个主题都有一个控制模板,而不是一个覆盖所有主题的集合。执行此操作的方法是将所有特定于主题的资源放入其自己的资源字典中。这些词典放在项目根目录中的 themes 子文件夹中,每个词典都以主题名称和主题颜色命名:ThemeName.ThemeColor.xaml。

请注意,您仍然使用SystemColorsSystemFontsSystemParameters,就像在简单方法中一样。

我没有可能列出Windows 7主题的新版本书,但以下是Adam在我的版本中列出的内容:

  • Vista Aero:themes \ Aero.NormalColor.xaml
  • XP默认值:themes \ Luna.NormalColor.xaml
  • XP green:themes \ Luna.Homestead.xaml
  • XP silver:themes \ Luna.Metallic.xaml
  • XP royale:themes \ Royale.NormalColor.xaml
  • XP Zune:themes \ Zune.NormalColor.xaml
  • 经典:主题\ 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中查找Classic主题资源字典。

最后,您在app资源字典中使用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)));