1
votes

I am currently writing a Dialog class (lookless control) which extends Window, and am assigning a default ControlTemplate to that class using a XAML style.

I want the 'Buttons' section of my Dialog template to be replacable, yet pre-populate it with a set of default buttons if nothing else is specified. This is why I added a dependency property called ButtonContent to my class.

The DefaultButtons (see XAML below) are rendered correctly when I run the application, but Visual Studio 2010's design preview does not render the content. Why is this not happening?

My dialog class looks like this:

public class Dialog : Window
{
    public FrameworkElement ButtonContent
    {
        get { return (FrameworkElement)GetValue(ButtonContentProperty); }
        set { SetValue(ButtonContentProperty, value); }
    }

    public static readonly DependencyProperty ButtonContentProperty =
        DependencyProperty.Register("ButtonContent", typeof(FrameworkElement), typeof(Dialog), new UIPropertyMetadata(null));

    static Dialog()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(Dialog), new FrameworkPropertyMetadata(typeof(Dialog)));
    }
}

This is my XAML:

<Style TargetType="{x:Type Dialogs:Dialog}">
    <Setter Property="DataContext" Value="{Binding RelativeSource={RelativeSource Self}}"/>     
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Dialogs:Dialog}">
                <StackPanel>
                    <ContentPresenter Content="{TemplateBinding ButtonContent}"/>
                    <TextBlock>This text is rendered correctly</TextBlock>
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>

    <Setter Property="ButtonContent">
        <Setter.Value>
            <!-- This stuff here is not shown in VS2010's preview -->
            <UniformGrid Name="DefaultButtons" Rows="1" Columns="2">
                <Button>Button 1</Button>
                <Button>Button 2</Button>
            </UniformGrid>
        </Setter.Value>
    </Setter>
</Style>

When I launch the app, it looks like this:

As rendered by the app

The VS2010 designer renders this:

As rendered by VS2010


Edit: As described in the comments, placing the above style in Themes\Generic.xaml instead of my resource dictionary included from App.xaml does not change anything.


Edit 2: If I explicitly override the default ButtonContent like this, the designer also does not show anything. At runtime, everything works perfectly:

<Dialogs:Dialog x:Class="Dialogs.TestDialog"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Dialogs="clr-namespace:Dialogs">
    <Dialogs:Dialog.ButtonContent>
        <Button>Also not shown at design time</Button>
    </Dialogs:Dialog.ButtonContent>
</Dialogs:Dialog> 

Edit 3: If I add the ButtonContent property to a UserControl instead of my Dialog class that extends Window, the ButtonContent is displayed correctly within the user control... also, VS2010 seems to apply the style defined above to any window, not just those of class Dialog, although I have set the TargetType appropriately... weird!

1
When you say "this is my xaml" do you mean the generic.xaml? A Default style should usually be placed there.dowhilefor
The designer doesn't render code, only XAML.Bob.
@dowhilefor: I placed it in a separate XAML that was included in a MergedDictionary within my App.xaml. I also tried putting the default dialog style in Generic.xaml as you suggested. This did not change anything at runtime; at design time, however, that style was apparently not being applied at all, so this is even worse than my previous approach.tlind
@Bob: But apparently, the designer does support this for the controls shipped with WPF by default (such as a ContentControl or a HeaderContentControl). Otherwise, the designer wouldn't render the content of a button or the header of tab items. Also, I do not really have much code – except for the static declaration of the dependency property!?tlind
Otherwise, the designer wouldn't render the content of a button or the header of tab items. Your picture only shows the TextBlock rendered in VS Designer. Runtime is different than what shows in the Designer.Bob.

1 Answers

1
votes

I opened up a bug report at Microsoft Connect for this issue. According to MS, it is a known issue and is by design:

Thanks for reporting this issue. This is a known issue on our end and is by design. We cannot create a design instance of Window within the designer so we substitute with a proxy type of our own. That is the reason why it works correctly in a UserControl and not in a window. The workaround is to design the content of the dialog separately as a UserControl.