Richard
Richard

Reputation: 1590

WPF Custom Window Template No Content

We are about to move to WPF and are currently working on a templated window.

After hours of reading and following tutorials on CodeProject and StackOverflow I am struggling with a, what I believe rather simple, problem in regards of transparency.

Solution Overview

How it looks in the preview

When I run the app, there is no "content" in my window.

I have my Style defined in Generic.xaml, which is located in the Themes folder.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:local="clr-namespace:MTApp"
                x:Class="MTApp.Themes.Generic">

<ControlTemplate x:Key="WindowTemplate" TargetType="{x:Type Window}">
    <Grid x:Name="WindowRoot">
        <Border x:Name="WindowFrame">
            <Grid Margin="0" VerticalAlignment="Top" MouseDown="Window_MouseDown">

                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="25"/>
                    <ColumnDefinition Width="75*"/>
                    <ColumnDefinition Width="75"/>
                    <ColumnDefinition Width="25"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="40" />
                    <RowDefinition Height="30" />
                    <RowDefinition Height="35" />
                    <RowDefinition Height="35" />
                    <RowDefinition Height="140*" />
                </Grid.RowDefinitions>
                <Frame x:Name="background" Grid.Column="0" Grid.ColumnSpan="4" Grid.Row="0" Background="#ddd" BorderThickness="0 0 0 1" BorderBrush="#c9c9c9"/>
                
                <Label x:Name="windowTitle" Grid.ColumnSpan="2" Content="Title Bar" VerticalAlignment="Center" Foreground="#393939" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Center" FontFamily="Segoe UI Regular" FontSize="12"/>
                <Grid Grid.Column="2" Grid.ColumnSpan="2" Grid.Row="0">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="50"/>
                        <ColumnDefinition Width="13"/>
                        <ColumnDefinition Width="14"/> 
                        <ColumnDefinition Width="13"/>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="15"/>
                        <RowDefinition Height="10" />
                        <RowDefinition Height="10" />
                    </Grid.RowDefinitions>
                    <Button x:Name="minimizeBtn" Content="" Background="#39b54a" BorderThickness="0" Grid.Row="1" Grid.Column="1" Margin="3 0 0 0" Click="minimizeBtn_Click"/>
                    <Button x:Name="maximizeBtn" Content="" Background="#f8be3f" BorderThickness="0" Grid.Row="1" Grid.Column="2" Margin="3 0 0 0" Click="maximizeBtn_Click"/>
                    <Button x:Name="quitBtn" Content="" Background="#f84646" BorderThickness="0" Click="quitBtn_Click" Grid.Row="1" Grid.Column="3" Margin="3 0 0 0"/>
                </Grid>
            </Grid>
        </Border>
    </Grid>
</ControlTemplate>

<Style x:Key="SkinWindowStyle" TargetType="Window">
    <Setter Property="WindowStyle" Value="None" />
    <Setter Property="AllowsTransparency" Value="True" />
    <Setter Property="Background" Value="#ffffff" />
    <Setter Property="Opacity" Value="100" />        
    <Setter Property="ResizeMode" Value="CanResize" />
    <Setter Property="Width" Value="600" />
    <Setter Property="Height" Value="300" />
    <Setter Property="Template" Value="{StaticResource WindowTemplate}" />

    <Style.Triggers>
        <DataTrigger Binding="{Binding WindowState}" Value="Maximized">
        </DataTrigger>
    </Style.Triggers>
</Style>

It defines "WindowStyle" and "AllowsTransparency" as seen in many tutorials, if I set "AllowsTransparancy" to False I will get a border full black window.

As you can see from the style already, I want to have the background white. But All I get is an "empty" window. I wanted to force some witdh onto it, as you can see from the other setter items.

My MainWindow.xaml, which is the actuall app looks like this:

<Window x:Class="MTApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Style="{DynamicResource SkinWindowStyle}"    
    Background="White"
    Height="300"
    Width="350"        
    >
<Grid Background="White" Height="100" Width="200">        
    <TextBlock Text="Test" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" Background="White"/>
</Grid>

It uses the style defined in Generic.xaml, which all works fine. Sure, the Background, Height and Width cannot overwrite the style's properties, because its hard coded, but still, the Grid should be shown as well as the text box. But none of these appear.

Lastly, the Generic.xaml.cs:

    using System;
using System.Windows;
using System.Windows.Input;

namespace MTApp.Themes
{ 
    public partial class Generic : ResourceDictionary
    {

        public Generic()
        {
            InitializeComponent();
        }

        /**
        * Header Buttons Events
        **/
        private void minimizeBtn_Click(object sender, RoutedEventArgs e)
        {
            Application.Current.MainWindow.WindowState = WindowState.Minimized;
        }

        private void maximizeBtn_Click(object sender, RoutedEventArgs e)
        {
            if (Application.Current.MainWindow.WindowState == WindowState.Maximized)
            {
                Application.Current.MainWindow.WindowState = WindowState.Normal;
            }
            else
            {
                Application.Current.MainWindow.WindowState = WindowState.Maximized;
            }

        }

        private void quitBtn_Click(object sender, RoutedEventArgs e)
        {
            Window.GetWindow(((FrameworkElement)e.Source)).Close();
        }

        /** 
        * Window Events
        **/
        private void Window_MouseDown(object sender, MouseButtonEventArgs e)
        {

            if (e.ChangedButton == MouseButton.Left)
            {
                Window.GetWindow(((FrameworkElement)e.Source)).DragMove();
            }

        }

    }
}

Mind you, its derived from ResourceDictionary, I could not get it working from "Window" as seen in the 5 tutorials available online...

So here my question, why is nothing shown below my custom content ? Do I need to specify a certain canvas on which we can then put our controls for each window ? Think login window, options window, message/confirm window. They should all share the same style, and hence we want to have the window templated.

Upvotes: 0

Views: 2616

Answers (1)

andreask
andreask

Reputation: 4298

To allow adding controls to the window, you need to add a ContentPresenter control to the ControlTemplate. Add the following to the template code:

<ControlTemplate x:Key="WindowTemplate" TargetType="{x:Type Window}">
    <Grid x:Name="WindowRoot">
        <Border x:Name="WindowFrame">
            <Grid Margin="0" VerticalAlignment="Top">

                <Grid.ColumnDefinitions>
                    ...
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    ...
                </Grid.RowDefinitions>

                ... header controls ...

                <ContentPresenter Grid.Column="0" Grid.ColumnSpan="4" Grid.Row="1"/>
            </Grid>
        </Border>
    </Grid>
</ControlTemplate>

Of course, the ContentPresenter's Grid.Row and Grid.Column settings need to be adapted, depending on where you'd like the window content to be inserted.

Upvotes: 1

Related Questions