PROBLEM:
The main window of my application will have 3 areas:
1) A header where there will be diferent controls such as links, menus, images, etc, besides a previous/next navigation button with customized appearance;
2) A footer with more controls on it;
3) A content area where different pages will be displayed.
SOLUTION CONSIDERED:
WindowsFX provides a build-in NavigationWindow that can be customized using ControlTemplate mechanism. It comes with a default Header (with buttons) and a page area.
I decided it would be convenient to inherit from the NavigationWindow, define 2 DependencyProperties: one to hold a control for the header and the other to hold the control for the footer, and then to use those properties in the control template.
QUESTION:
How can I instantiate a control for the header and for the footer in XAML
I can do it using code, for example:
public partial class MyCustomNavigationWindow : NavigationWindow
{
public static DependencyProperty HeaderProperty;
public static DependencyProperty FooterProperty;
static MyCustomNavigationWindow()
{
PropertyMetadata headerMetadata = new PropertyMetadata();
HeaderProperty = DependencyProperty.Register("Header", typeof(FrameworkElement), typeof(MyCustomNavigationWindow), headerMetadata);
PropertyMetadata footerMetadata = new PropertyMetadata();
FooterProperty = DependencyProperty.Register("Footer", typeof(FrameworkElement), typeof(MyCustomNavigationWindow), footerMetadata);
}
public MyCustomNavigationWindow()
{
SetValue(HeaderProperty, new Button());
SetValue(FooterProperty, new Button());
InitializeComponent();
}
}
< Mapping XmlNamespace="App" ClrNamespace="App" >
<NavigationWindow x:Class="App.MyCustomNavigationWindow"
xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"
xmlns:App="App"
Title="App"
>
<NavigationWindow.Style>
<Style>
<Setter Property="NavigationWindow.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type NavigationWindow}">
<DockPanel>
<ContentControl DockPanel.Dock="Top" Content="{TemplateBinding App:MyCustomNavigationWindow.Header}"/>
<ContentControl DockPanel.Dock="Bottom" Content="{TemplateBinding App:MyCustomNavigationWindow.Footer}"/>
<ContentPresenter ClipToBounds="True" Content="{TemplateBinding Window.Content}"/>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</NavigationWindow.Style>
<!-- THE FOLLOWING WAY DOESN'T WORK:
<App:MyCustomNavigationWindow.Header>
<Button/>
</App:MyCustomNavigationWindow.Header>
<App:MyCustomNavigationWindow.Footer>
<Button/>
</App:MyCustomNavigationWindow.Footer>
-->
</NavigationWindow>
Where can I find information/examples on how to define and use property aliasing and/or create things like ContentPresenter
Regardless, is this really the most appropriate solution
Thanks for reading until here!

Customizing NavigationWindow and using Property Aliasing
Matt Thubron
innivodave
Ah, it looks like the DP isn't setup correctly. While your version works fine programmatically, it needs to be declared a certain way to work in XAML, which is the recommended practice. The WPF extensions for VS include a snippet for this. If you type 'propdp' then tab a couple times, you get a snippet for doing this. So your Header would look like this:
public FrameworkElement Header
{
get { return (FrameworkElement)GetValue(HeaderProperty); }
set { SetValue(HeaderProperty, value); }
}
// Using a DependencyProperty as the backing store for Header. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HeaderProperty =
DependencyProperty.Register("Header", typeof(FrameworkElement), typeof(MyCustomNavigationWindow), new UIPropertyMetadata(0));
That will build.
- Daniel
Mark 5762
basav
Currently, the XamlReader is not able to set properties on the newly defined class.
A workaround until we support this (likely after v1 if we do):
Create your subclass of the NavigationWindow:
class MyCustomNavigationWindow : NavigationWindow
{
...
//define Footer and header in this class
...
}
In your xaml file, use app:MyCustomNavigationWindow as the root element. Create x:Class="MyCustomNavWindow1" or whatever...
That should do the trick.
Not positive we'll change to support this, but you should be unblocked...and at least understand the problem...
Thx, Rob Relyea
WPF, PM
http://longhornblogs.com/rrelyea
srikanthb
However, I still can't set the dependencies properties in XAML. The markup in red gives a compilation error that says:
Error 10 Unrecognized tag 'MyCustomNavigationWindow.Header' in namespace 'clr-namespace:App'. Note that tag names are case sensitive. Line 28 Position 4.
<App:MyCustomNavigationWindow
x:Class="App.MyCustomNavigationWindow1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:App="clr-namespace:App"
Title="App"
>
<NavigationWindow.Style>
<Style>
<Setter Property="NavigationWindow.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type App:MyCustomNavigationWindow}">
<DockPanel>
<ContentControl DockPanel.Dock="Top" Content="{TemplateBinding App:MyCustomNavigationWindow.Header}"/>
<ContentControl DockPanel.Dock="Bottom" Content="{TemplateBinding App:MyCustomNavigationWindow.Footer}"/>
<ContentPresenter ClipToBounds="True" Content="{TemplateBinding Window.Content}"/>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</NavigationWindow.Style>
<!-- SHOULD THE FOLLOWING WORK -->
<App:MyCustomNavigationWindow.Header>
<Button/>
</App:MyCustomNavigationWindow.Header>
<App:MyCustomNavigationWindow.Footer>
<Button/>
</App:MyCustomNavigationWindow.Footer>
</App:MyCustomNavigationWindow>
If I set the properties in code - for example in the MyCustomNavigationWindow constructor - everything works as it did in JanuaryCTP.
Basically my big question is:
How can I set a complex dependency property of an inherited Window in XAML
-Makutaku
cpf
pelandry
Thanks for your reply. It's nice to now I have stepped into a limitation.
I have applied all of your changes. However I still couldn't set the header and footer in XAML. The markup in red doesn't work. I get an error saying "Unknown tag MyCustomNavigationWindow.Header".
< Mapping XmlNamespace="App" ClrNamespace="App" >
<App:MyCustomNavigationWindow
x:Class="App.MyCustomNavigationWindow1"
xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"
xmlns:App="App"
Title="App"
>
<NavigationWindow.Style>
<Style>
<Setter Property="NavigationWindow.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type App:MyCustomNavigationWindow}">
<DockPanel>
<ContentControl DockPanel.Dock="Top" Content="{TemplateBinding App:MyCustomNavigationWindow.Header}"/>
<ContentControl DockPanel.Dock="Bottom" Content="{TemplateBinding App:MyCustomNavigationWindow.Footer}"/>
<ContentPresenter ClipToBounds="True" Content="{TemplateBinding Window.Content}"/>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</NavigationWindow.Style>
<!-- SHOULD THE FOLLOWING WORK -->
<App:MyCustomNavigationWindow.Header>
<Button/>
</App:MyCustomNavigationWindow.Header>
<App:MyCustomNavigationWindow.Footer>
<Button/>
</App:MyCustomNavigationWindow.Footer>
</App:MyCustomNavigationWindow>
When I do it in code it works fine:
public MyCustomNavigationWindow()
{
SetValue(HeaderProperty, new Button());
SetValue(FooterProperty, new Button());
}
Marcelh
Thanks again for your help !
-Makutaku