Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Adding controls to a NavigationWindow's chrome

2 views
Skip to first unread message

Keith Patrick

unread,
Sep 19, 2005, 2:12:31 AM9/19/05
to
The WPF documentation says that in addition to removing and replacing the
navigation chrome, it can be customized. I'm trying to add a crumb trail
beneath the window title, but the best I can do is build a new one up from
scratch, but going that route, I lose the native look and feel of the
standard buttons. Anyone know how insert a control into the navigation
area? I can find it in the watch window, but not via any public properties
to do it declaratively in XAML.


Keith Patrick

unread,
Sep 19, 2005, 5:42:14 PM9/19/05
to
And here's the full style for NavigationWindow. This gives me some names to
hit (like the border I want to use). Ultimately, I can redraw the border
itself and leave everything else. It's still slightly more markup than I
wanted (I'd rather add the control instead of redeclaring the
butttons/text), but it still gets me what I wanted:
<Style xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005" TargetType="{x:Type
NavigationWindow}"><Setter
Property="FontFamily"><Setter.Value><DynamicResourceExtension
ResourceKey="{x:Static SystemFonts.MessageFontFamilyKey}"
/></Setter.Value></Setter><Setter
Property="FontSize"><Setter.Value><DynamicResourceExtension
ResourceKey="{x:Static SystemFonts.MessageFontSizeKey}"
/></Setter.Value></Setter><Setter
Property="FontStyle"><Setter.Value><DynamicResourceExtension
ResourceKey="{x:Static SystemFonts.MessageFontStyleKey}"
/></Setter.Value></Setter><Setter
Property="FontWeight"><Setter.Value><DynamicResourceExtension
ResourceKey="{x:Static SystemFonts.MessageFontWeightKey}"
/></Setter.Value></Setter><Setter
Property="TextDecorations"><Setter.Value><DynamicResourceExtension
ResourceKey="{x:Static SystemFonts.MessageFontTextDecorationsKey}"
/></Setter.Value></Setter><Setter
Property="Foreground"><Setter.Value><DynamicResourceExtension
ResourceKey="{x:Static SystemColors.WindowTextBrushKey}"
/></Setter.Value></Setter><Setter
Property="Background"><Setter.Value><DynamicResourceExtension
ResourceKey="{x:Static SystemColors.WindowBrushKey}"
/></Setter.Value></Setter><Setter
Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type
NavigationWindow}"><Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" ClipToBounds="True"
Name="NavigationBarRoot"><DockPanel><Border Background="LinearGradient 0,0
1,0 #FFC0C0C0 #FFFFFFFF" DockPanel.Dock="Top"
Name="NavigationBarBackground"><DockPanel><Button DockPanel.Dock="Left"
IsEnabled="{TemplateBinding CanGoBack}" Style="{DynamicResource
PFThemeNavigationWindowNavigationButtonBackButtonStyle}" /><Button
DockPanel.Dock="Left" IsEnabled="{TemplateBinding CanGoForward}"
Style="{DynamicResource
PFThemeNavigationWindowNavigationButtonForwardButtonStyle}" /><TextBlock
FontSize="16" Foreground="{DynamicResource {x:Static
SystemColors.ActiveCaptionTextBrushKey}}" Margin="8,0,0,0"
VerticalAlignment="Center"><TextBlock.Text><?Mapping
XmlNamespace="mscorlib_System_1ns" ClrNamespace="System" Assembly="mscorlib"
?><mscorlib_System_1:String
xmlns:mscorlib_System_1="mscorlib_System_1ns">asdfa</mscorlib_System_1:String></TextBlock.Text></TextBlock><Button
DockPanel.Dock="Bottom">WOrks</Button></DockPanel></Border><Grid><ColumnDefinition
Width="*" /><RowDefinition Height="*" /><RowDefinition Height="Auto"
/><AdornerDecorator Grid.Column="0" Grid.Row="0"><ContentPresenter
ClipToBounds="True" Content="{TemplateBinding Content}"
/></AdornerDecorator><ResizeGrip Background="#00FFFFFF" Grid.Column="0"
Foreground="{DynamicResource {x:Static
SystemColors.ControlDarkDarkBrushKey}}" Height="23"
HorizontalAlignment="Right" IsTabStop="False" Name="WindowResizeGrip"
Grid.Row="0" Grid.RowSpan="2" VerticalAlignment="Bottom"
Visibility="Collapsed" Width="14"
/></Grid></DockPanel></Border><ControlTemplate.Triggers><MultiTrigger><MultiTrigger.Conditions><Condition
Property="ResizeMode" Value="CanResizeWithGrip" /><Condition
Property="WindowState" Value="Normal" /></MultiTrigger.Conditions><Setter
TargetName="WindowResizeGrip" Property="Visibility" Value="Visible"
/></MultiTrigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style>


Drew Marsh

unread,
Sep 19, 2005, 6:04:06 PM9/19/05
to
Keith Patrick wrote:

> And here's the full style for NavigationWindow. This gives me some
> names to hit (like the border I want to use). Ultimately, I can redraw the
> border itself and leave everything else. It's still slightly more markup
> than I wanted (I'd rather add the control instead of redeclaring the
> butttons/text), but it still gets me what I wanted:

Yeah having to redo the whole chrome kinda stinks. :\ If they change the
default template on you your application is no longer going to look the same,
so it defeats the whole purpose.

That sample I posted earlier where you nest the original template within
the redefine is how it "should" work, but the fact that it's a Window control
is the problem there. :(

-Drew


Dennis Cheng [MSFT]

unread,
Sep 19, 2005, 6:37:28 PM9/19/05
to
What CTP release are you using Drew? This style works with the September CTP
release:

<NavigationWindow>
<NavigationWindow.Style>
<Style TargetType="{x:Type NavigationWindow}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border Margin="10" CornerRadius="10" BorderThickness="2"
BorderBrush="blue" Background="silver">
<ContentPresenter Margin="10" Content="{TemplateBinding
NavigationWindow.Content}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
...

--
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm

"Drew Marsh" <dru...@hotmail.no.spamming.com> wrote in message
news:b6983b4c9f0f98...@msnews.microsoft.com...
> Keith Patrick wrote:
>
>> I'm not quite following you on that.
>
> Basically what I meant was this:
>
> <NavigationWindow ...>
> <NavigationWindow.Style>
> <Style TargetType="{x:Type NavigationWindow}">


> <Setter Property="Template">
> <Setter.Value>
> <ControlTemplate TargetType="{x:Type NavigationWindow}">

> <NavigationWindow Style="{x:Null}">
> <Grid>
> <ColumnDefinition/>
> <RowDefinition Height="100"/>
> <RowDefinition/>
>
> <Rectangle Fill="Red" Grid.Column="0" Grid.Row="0"/>
> <ContentPresenter Content="{TemplateBinding Content}"/>
> </Grid>
> </NavigationWindow>
> </ControlTemplate>
> </Setter.Value>
> </Setter>
> </Style>
> </NavigationWindow.Style>
> </NavigationWindow>
>
> However, don't bother trying it... it doesn't work. :( I get the following
> exception:
>
> "Window must be the root of the tree. Cannot add window as a Logical or
> Visual child of any Visual."
>
> Which makes sense in 99.9% of the scenarios, but is unfortunate for this
> scenario. I guess we'll have to wait for a Microsoft rep to take a look at
> this scenario and provide a suggestion now. Sorry!
>
> Cheers,
> Drew
>
> ___________________________________
> Drew Marsh
> Chief Software Architect
> Mimeo.com, Inc. - http://www.mimeo.com
> Weblog - http://blog.hackedbrain.com/
>
>


Drew Marsh

unread,
Sep 19, 2005, 7:00:21 PM9/19/05
to
Dennis Cheng wrote:

> What CTP release are you using Drew? This style works with the
> September CTP release:
>
> <NavigationWindow>
> <NavigationWindow.Style>
> <Style TargetType="{x:Type NavigationWindow}">
> <Setter Property="Template">
> <Setter.Value>
> <ControlTemplate>
> <Border Margin="10" CornerRadius="10" BorderThickness="2"
> BorderBrush="blue" Background="silver">
> <ContentPresenter Margin="10" Content="{TemplateBinding
> NavigationWindow.Content}"/>
> </Border>
> </ControlTemplate>
> </Setter.Value>
> </Setter>
> </Style>

Yeah, that works no problem. Take a look at my declaration again. You'll
see that I'm attempting to actually just add to the default template by declaring
my own control template which in turn uses the default template declaration
for NavigationWindow inside of it. As a simpler example, imagine I wanted
all Labels in my application to have a border around them, I would do the
following (syntax not checked):

<Style x:Key="{x:Type Label}" TargetType="{x:Type Label}">
<Style Property="Template">
<Style.Value>
<Border BorderBrush="Red" BorderThickness="2">
<Label Style="{x:Null}" Content="{TemplateBinding Content}"/>
</Border>
</Style.Value>
</Style>
</Style>

So I'm redefining the default look of all Label's by adding a border around
them, yet retaining the built in look/functionality of the control within
the template because of the explicit Style="{x:Null}".

HTH,
Drew


Michael Latta

unread,
Sep 19, 2005, 7:04:13 PM9/19/05
to
I would not expect this to work. Your style hides the standard styles.
They are not keyed to null, but to the type as far as I have seen so far. I
agree that more OO like features to override but reuse would be great. I
have had cases where I wanted to subtype a style/template and
disable/replace one setter/trigger but had to duplicate the entire
style/template to do that, and in the process bake in one theme, when I
really would rather use the current theme with that one change.

Michael


"Drew Marsh" <dru...@hotmail.no.spamming.com> wrote in message

news:b6983b4c9f3748...@msnews.microsoft.com...

Drew Marsh

unread,
Sep 19, 2005, 12:07:35 PM9/19/05
to
Keith Patrick wrote:

I haven't ever tried to Style/Template the navigation chrome myself, but
you should be able to nest the standard chrome control with a Style="{x:Null}"
inside of your Template which should give you the ability to add content
*around* the standard chrome.

Be sure to let us know how it works out for you!

Cheers,
Drew


Keith Patrick

unread,
Sep 19, 2005, 7:34:02 PM9/19/05
to
I'm basically going for a fully custom chrome now. I'd prefer to be able to
override the style on a named template item (in this case the BarRoot
border), but since it was holding me up, I put in one with a different
title, a collapsable description bar, and crumb trail; I'm also docking a
transparency/scale standard control here as well. It's one of those areas
where the logical vs. visual separation is coming in handy. I've only been
using this stuff for 2 weeks, but the flexibility, speed, and results are
blowing me away; I'm finally getting around to writing some UIs I've been
unable to make via GDI in a reasonable timeframe (sorry for sounding like an
infomercial).


Drew Marsh

unread,
Sep 19, 2005, 7:33:29 PM9/19/05
to
Michael Latta wrote:

> I would not expect this to work. Your style hides the standard
> styles. They are not keyed to null, but to the type as far as I have
> seen so far.

Duh, that's a good point. I guess it wouldn't retain any "look" at that point,
just behavior. Hmmm... been a long day I guess, my brain's not quite workin'
the way it should. Guess I spent too much time at the PDC. ;P

So then, does Keith really have to recreate the whole header template himself
just to "append" to the header? Granted he can use the correct style keys
to get the look of the individual controls himself (i.e. PFThemeNavigationWindowNavigationButtonBackButtonStyle),
but that doesn't guarentee him the same layout. Couldn't the navigation chrome
of the window be made into an individual control and NavigationWindow itself
just be a HeaderedContentControl which by default templates the header as
the navigation chrome control and then the pages get loaded into the content??

Cheers,
Drew


Keith Patrick

unread,
Sep 19, 2005, 1:47:59 PM9/19/05
to
I'm not quite following you on that. Are you saying to apply Style="x:Null"
to the chrome control within the template? If so, how do I reference the
chrome control? I can find it as a private member of Visual called
_childCollection.Items[0], but anything I do with this.MainWindow.Content
only affects the area below the chrome. I would think it's possible, since
I've seen some early Explorer builds that had a crumb trail, and that's the
effect I'm trying to get.
I think it has something to do with ContentPresenter, but I'm having a hell
of a time figuring out how to use it (saying
ContentControl.Content="{TemplateBinding Property=Content}" doesnt' seem to
work, giving me a black window with the content area only sitting over it.


Keith Patrick

unread,
Sep 19, 2005, 2:22:06 PM9/19/05
to
BTW: Here is my code (at least what I'm trying to get to work right now):
<Application.Resources>

<Style TargetType="{x:Type NavigationWindow}">
<Setter Property="NavigationWindow.Template">

<Setter.Value>
<ControlTemplate TargetType="{x:Type NavigationWindow}">
<ContentPresenter
ContentControl.Content="{TemplateBinding NavigationWindow.Content}"
ClipToBounds="True"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>


Drew Marsh

unread,
Sep 19, 2005, 3:07:54 PM9/19/05
to
Keith Patrick wrote:

> I'm not quite following you on that.

Basically what I meant was this:

<NavigationWindow ...>
<NavigationWindow.Style>


<Style TargetType="{x:Type NavigationWindow}">

<Setter Property="Template">


<Setter.Value>
<ControlTemplate TargetType="{x:Type NavigationWindow}">

Keith Patrick

unread,
Sep 19, 2005, 3:59:05 PM9/19/05
to
I got some more interesting results with the following:
<Application.Resources>
<Style x:Key="{x:Type NavigationWindow}" TargetType="{x:Type
NavigationWindow}"
BasedOn="{StaticResource {x:Static
SystemParameters.NavigationChromeDownLevelStyleKey}}">
</Style>
</Application.Resources>
If I base it on thi sDownLevel style, I'll get a small version of the nav
chrome (with green instead of blue highlighted buttons, too), minute with
WindowTitle. I'm not sure what to do with it, but it's interesting
nonetheless; maybe I can build a new chrome and just give it the style from
the built-in chrome rather than manipulate the existing chrome.
Unfortunately, I can't find info on that particular style yet.


Michael Latta

unread,
Sep 19, 2005, 8:12:15 PM9/19/05
to
Unfortunately this appears to be a common theme these days. If you want to
change anything you need to redefine the entire template/style. This is
going to mean a lot of applications are hard coded to a single theme/style.
That means things are not going to look alike from one theme to another.
While it is possible to define a version of each style for each theme, I
doubt this will in fact happen in any but the large software vendors.

Michael


"Keith Patrick" <richard_ke...@nospam.hotmail.com> wrote in message
news:OyRUdKXv...@TK2MSFTNGP15.phx.gbl...

Drew Marsh

unread,
Sep 19, 2005, 5:40:36 PM9/19/05
to
Keith Patrick wrote:

Hmm, that's an interesting approach I didn't think of. Did you try the SystemParameters.NavigationChromeStyleKey[1]
for BasedOn instead??? Might give you the "real" chrome as opposed to whatever
this "down level" chrome is.

-Drew

[1] http://winfx.msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/P_System_Windows_SystemParameters_NavigationChromeStyleKey.asp


Dennis Cheng [MSFT]

unread,
Sep 19, 2005, 9:05:29 PM9/19/05
to
Unfortunately, there isn't a way to selectively modify one part within the
ControlTemplate when a style is "BasedOn" another. You could create a custom
control that uses a modified version of the NavigationWindow's
ControlTemplate to use in your NavigationWindow template or manually insert
your custom elements within NavigationWindow's visual tree using the
VisualOperations class.

--
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm

"Drew Marsh" <dru...@hotmail.no.spamming.com> wrote in message
news:b6983b4c9f3788...@msnews.microsoft.com...

0 new messages