开发者

How can I get my UserControl to look like a 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?


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)));
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜