Question

How to derive from RibbonWindow?

Posted 5 years ago by Avatar Matthias Butterweck
Hi!

I would like to write a class that inherits from RibbonWindow.
In my new class I would like to have a few buttons at the bottom of a dockpanel.
The rest of the dockpanel should be filled with what he user defines later.

My class looks like this:
namespace helic.Wpf
{
    public class DerivedRibbonWindow : RibbonWindow
    {
        static DerivedRibbonWindow()
        {
            DefaultStyleKeyProperty.OverrideMetadata(
                typeof(DerivedRibbonWindow), 
                new FrameworkPropertyMetadata(typeof(DerivedRibbonWindow)));
        }
        public DerivedRibbonWindow() 
        {
        }
    }
}
I defined a style in Themes\generic.xaml resource of the assembly like this:
<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:helic.Wpf">
    <Style TargetType="{x:Type local:DerivedRibbonWindow}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:DerivedRibbonWindow}">
                    <DockPanel LastChildFill="True" >
                        <!-- these are the buttons to be displayed 
                             in every DerivedRibbonWindow -->
                        <StackPanel Orientation="Horizontal">
                            <Button>My Button</Button>
                            <Button>My Button</Button>
                            <Button>My Button</Button>
                        </StackPanel>
                        <!-- this is where the content should go! -->
                        <ContentPresenter
                            Content="{TemplateBinding ContentControl.Content}"
                            ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"/>
                    </DockPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>
In another assembly I tried to use this class in XAML like this:
<my:DerivedRibbonWindow
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ribbon="http://schemas.actiprosoftware.com/winfx/xaml/ribbon"
    xmlns:my="http://schemas.comline-ag.de/winfx">
    <TextBlock>Hello world</TextBlock>
</my:DerivedRibbonWindow>
When this window is shown all the entire content is black.

When I derive from Window instead of RibbonWindow the content is also black, but I can see at least the windows title bar.

So, is there a way to derive from RibbonWindow?

[Modified at 05/02/2009 08:40 AM]

Comments (7)

Posted 5 years ago by Actipro Software Support - Cleveland, OH, USA
Matthias,

The way you are doing it there will prevent the RibbonWindow from being templated and thus it will be black. You can inherit RibbonWindow but don't override the style key. RibbonWindow uses a custom Template to give it its skin.

I have an idea for a possible way to do what you want though. Try to define a new dependency property of type object maybe called ChildContent.

In your RibbonWindow class's XAML, have your StackPanel etc. as the Content and add the ContentPresenter but bind the ContentPresenter's content to your new ChildContent property.

Then maybe also add a ContentProperty attribute and point it to your ChildContent property. This way you could probably create instances of DerivedRibbonWindow like you did in your last code snippet and have it all work.

Actipro Software Support
Posted 5 years ago by Yvan Charbonnier
Could you provide a code sample.

I'm quite new in WPF and it seems to me to be outside the usual "practice" of custom control styling.
Thanks in advance
Posted 5 years ago by Actipro Software Support - Cleveland, OH, USA
Hi Yvan,

When talking about Styling, you don't need to derive the RibbonWindow in order to restyle it. You would just need to alter the default Style (e.g. by adding your buttons). Then you can include that modified Style in your resources and it would be automatically applied.

If you are an existing customer we can send you the default Styles, which you can then modify as needed. Just send a request over to our support email address.

With the idea above, you can leverage the fact that you can easily retemplate the "ontent" presented by the window to accomplish the same look/feel. Additionally, you don't have to worry about providing a Style for all the supported themes (which you would have to if you derive from RibbonWindow and want to be able to easily switch themes), which adds a bit more work.

The steps for adding another property would be (this is off the top of my head):

1. Add a DependencyProperty to your derived class of type Object, let's call this ChildContent.
2. Add [ContentProperty("ChildContent")] above your Window class declaration.
3. Remove the DefaultStyleKeyProperty.Override(...) line from the static constructor
4. In the XAML code, remove the Setter for the Template property.
5. In the XAML code, add the following Setter:
<Setter Proeprty="ContentTemplate">
    <Setter.Value>
        <DataTemplate>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>

                <ContentPresenter Content="{Binding ChildContent, RelativeSource={RelativeSource AncestorType={x:Type yourns:DerivedRibbonWindow}}}" />
                <StackPanel Grid.Row="1">
                    ... add buttons ...
                </StackPanel>
            </Grid>
        </DataTemplate>
    </Setter.Value>
</Setter>
This basically reserves Content/ContentTemplate/ContentTemplateSelector for your custom template, but adds ChildContent for the end users to use. You can add ChildContentTemplate/Selector properties also, just be sure to bind them in the ContentPresenter like ChildContent is.

Actipro Software Support
Posted 5 years ago by Matthias Butterweck
Thanks!
With the code above I solved the problem.
I added the ChildContent DP to my class and put the style with TargetType="DerivedRibbonWindow" and the ContentTemplate-Setter into my generic.xaml file. For some reason the generic.xaml file wasn't loaded automagically. Maybe this is because the DerivedRibbonWindow has no xaml? So I added a line to the constructor of the DerivedRibbonWindow", and then everything worked as planned
public DerivedRibbonWindow() {
  this.Resources.MergedDictionaries.Add
    Application.LoadComponent(
      new System.Uri(
        "/MyAssembly;component/themes/generic.xaml", 
        System.UriKind.Relative));
}
Posted 5 years ago by Actipro Software Support - Cleveland, OH, USA
Hi Matthias,

Please make sure that you have the following line in your AssemblyInfo.cs file:
[assembly: ThemeInfo(ResourceDictionaryLocation.SourceAssembly, ResourceDictionaryLocation.SourceAssembly)]
That may correct the loading of the Generic.xaml file.

Regardless, you should probably move the Style for your DerivedRibbonWindow to another location. The XAML files under themes are really meant for theme related items. Your Style is more an implicit Style, just used set the ContentTemplate. But it's up to you :-)

Actipro Software Support
Posted 5 years ago by Yvan Charbonnier
Hi,

I Might be doing something wrong but I couldn't achieve the styling when removing the DefaultStyleKeyProperty.OverrideMetadata.

Well I have:
[ContentProperty("ChildContent")]
    public class EdhWindow: RibbonWindow
    {

        public static readonly DependencyProperty ChildContentProperty =
            DependencyProperty.Register("ChildContent", typeof (object), typeof (EdhWindow));

        public object ChildContent
        {
            get { return (object) GetValue(ChildContentProperty); }
            set { SetValue(ChildContentProperty, value); }
        }
        
  }
And as a Resource Dictionary:
<Style x:Key="{x:Type Core:EdhWindow}" TargetType="{x:Type Core:EdhWindow}">
        <Setter Property="ContentTemplate">
            <Setter.Value>
                <DataTemplate>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
 <ContentPresenter Content="{Binding ChildContent, RelativeSource={RelativeSource AncestorType={x:Type Core:EdhWindow}}}" />
                        <StackPanel Grid.Row="1">
                            <Button />
                            <Button />
                            <Button />
                            <Button />
                        </StackPanel>
                    </Grid>

                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>
I have all the ThemeInfo stuff in AssemblyInfo.cs, still the Style doesn't apply to window.

If I keep de DefaultStyleKeyProperty.OverrideMetadata and I Add a
BasedOn="{StaticResource {x:Type ribbon:RibbonWindow}}"
to the style definition,
this will do the trick and display the window correctly.

What are the "dark" effect styling ribbonWindow that way? How change the above code to work as you proposed? Will be any possibilité to display the new template in VS2008?

Thanks.
Posted 5 years ago by Actipro Software Support - Cleveland, OH, USA
As Matthias said above, he had to explicitly load the associated XAML file. You may need to do the same thing. Or you can put your Style in your Application.Resources.

If you build the default Style of your EdhWindow based on "{x:Type ribbon:RibbonWindow}", then it would not pick up theme changes (assuming you are changing the application theme during runtime). If you are not changing the theme during runtime, then this shouldn't be a problem.

The Style you have should work, assuming it is properly loaded and available to be applied to any instances of EdhWindow you create.

As for displaying the new template in VS2008, I'm assuming you are asking about the designer. If so, it should work fine (meaning you should be able to load up and design an instance of your EdhWindow ) but you'd have to verify that.

Actipro Software Support
Information The latest build of this product (2014.1 build 0602) was released 3 months ago, which was after the last post in this thread.

Add a Comment

Please log in to a validated account to post comments.