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

发布于 2024-10-17 18:56:57 字数 423 浏览 2 评论 0原文

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

在 Blend 中,我可以“编辑模板/编辑副本...”真实的 ComboBox 来获取使其看起来正确所需的零碎内容。适用于一种 Windows 主题 (Aero)。如果应用程序在另一个主题(例如 Luna)上运行,则控件不会改变其外观,它仍然具有 Aero 外观。

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

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

I have a user control containing a TextBox, ToggleButton and Popup, just like the real ComboBox. Now my problem is to style it so that it looks just like the normal ComboBox.

In Blend, I can "Edit Template/Edit a Copy..." of a real ComboBox to get the bits and pieces I need to get it to look right. For one Windows theme (Aero). If the application is run on another theme (e.g Luna), the control does not change its look, it still has the Aero look.

Do I have to supply a style/template for each Windows theme, or can I somehow get hold of (at run-time) the default ComboBox style and apply it to my UserControl?

Instead of making a UserControl, I have tried modifying a real ComboBox to my needs, but I just couldn't get it to work. How can I replace ALL the logic of a ComboBox with my own?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

不交电费瞎发啥光 2024-10-24 18:56:57

利用 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 绿色:主题\Luna.Homestead.xaml
  • XP 银色:主题\Luna.Metallic.xaml
  • XP 皇家:主题\Royale.NormalColor.xaml
  • XP Zune:主题\Zune.NormalColor.xaml
  • 经典:主题\Classic.xaml

这些将自动加载,并在主题更改时关闭。当它尝试加载您尚未创建匹配的资源字典的主题时,您还可以将主题\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)));

Taking advantage of Windows themes would be one way to approach this. Most of this is paraphrased and truncated from Windows Presentation Foundation Unleashed by Adam Nathan.

Simple Approach

You could use the resources and keys exposed by SystemColors, SystemFonts, and SystemParameters in your control template (along with DynamicResource, in case the theme is changed while your program is running) to set the appropriate values:

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

Robust Approach

The better way, though it requires more work, is to have a control template for each theme rather than one set that overrides everything. The way you do this is to put all your theme-specific resources into their own resource dictionary. These dictionaries are placed in a themes subfolder in the root of your project, and are each named after the theme name and theme color: ThemeName.ThemeColor.xaml.

Note that you still use SystemColors, SystemFonts, and SystemParameters, as in the simple approach.

I don't have the newer edition of the book that probably lists Windows 7 themes, but here are the ones Adam lists in the edition I have:

  • Vista Aero: themes\Aero.NormalColor.xaml
  • XP default: 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: themes\Classic.xaml

These will be automatically loaded, and switched out if the theme is changed. You can also specify themes\Generic.xaml as a default when it tries to load a theme that you haven't a created a resource dictionary to match.

You also have to opt-in to the automatic theming with ThemeInfoAttribute:

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

ResourceDictionaryLocation also has an ExternalAssembly option. The naming convention for these external assemblies is MainAssembly.ThemeName.dll, so if your assembly is called MyApp, it would look for the Classic theme resource dictionary in MyApp.Classic.dll.

And finally, you use ThemeDictionaryExtension in you app resource dictionary:

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

If you make any custom controls that derive from another control (not UserControl, but ProgressBar, for example), you should do this in its static constructor:

DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl),
    new FrameworkPropertyMetadata(typeof(MyControl)));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文