Search code examples
wpfwindowcontroltemplatesizetocontent

WPF Window ControlTemplate: How to handle SizeToContent


I've created style for type Window with set Template property. It works fine if I set Height and Width properties for window. But when I've tried to set SizeToContent="WidthAndHeight", the window's height and width were set to screen full height and width (even if all the content of the window is limited by height and width). Can SizeToContent be handled in control template?

Here's window style:

<Style x:Key="WindowStyle" TargetType="{x:Type Window}">
    <Setter Property="AllowsTransparency" Value="true" />
    <Setter Property="WindowStyle" Value="None" />
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="ResizeMode" Value="CanResizeWithGrip" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Window}">
                <Grid
                    Margin="7"
                    TextOptions.TextRenderingMode="ClearType"
                    TextOptions.TextFormattingMode="Display"
                    Background="Transparent">
                    <Border
                        x:Name="PART_Border"
                        Width="Auto"
                        Height="Auto"
                        Background="#EFEFF2"
                        BorderBrush="{StaticResource AppBrush}"
                        BorderThickness="1"
                        Padding="0"
                        CornerRadius="5">
                        <Border.Effect>
                            <DropShadowEffect
                                Color="black"
                                Opacity="0.5"
                                BlurRadius="7"
                                ShadowDepth="2"
                                Direction="315"/>
                        </Border.Effect>
                        <DockPanel
                            HorizontalAlignment="Stretch"
                            Background="Transparent"
                            VerticalAlignment="Stretch"
                            >
                            <Border
                                x:Name="TitleBar"
                                DockPanel.Dock="Top"
                                Background="#EFEFF2"
                                BorderThickness="0"
                                MouseLeftButtonDown="TitleBarMouseLeftButtonDown"
                                MouseMove="TitleBarMouseMove"
                                CornerRadius="5,5,0,0"
                                >
                                <Grid Height="35">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="36"/>
                                        <ColumnDefinition />
                                        <ColumnDefinition Width="26"/>
                                        <ColumnDefinition Width="26"/>
                                        <ColumnDefinition Width="26"/>
                                        <ColumnDefinition Width="25"/>
                                    </Grid.ColumnDefinitions>
                                    <Image
                                        x:Name="Icon"
                                        Grid.Column="0"
                                        Source="{Binding Path=Icon, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" 
                                        HorizontalAlignment="Right"
                                        Margin="4,-7,0,7"
                                        Width="32"
                                        Height="32"
                                        MouseLeftButtonDown="IconMouseLeftButtonDown"
                                        />
                                    <Label 
                                           Grid.Column="1"
                                           VerticalAlignment="Center"
                                           Content="{Binding Path=Title, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" FontFamily="FuturaDemiC" FontSize="18">
                                    </Label>
                                    <Button x:Name="MinButton"
                                            Grid.Column="2"
                                            Width="20"
                                            Height="20"
                                            Style="{StaticResource ImageButton}"
                                            Click="MinButtonClick"                                                
                                        >
                                        <Image Source="{StaticResource App_Minimize}"/>
                                    </Button>
                                    <Button x:Name="MaxButton"                                                 
                                            Grid.Column="3"
                                            Width="20"
                                            Height="20"
                                            Style="{StaticResource ImageButton}"
                                            Click="MaxButtonClick"

                                        >
                                        <Image Name="MaxButtonImage"
                                               Source="{StaticResource App_Maximize}" />
                                    </Button>
                                    <Button x:Name="CloseButton" 
                                            Grid.Column="4"
                                            Width="20"
                                            Height="20"
                                            Style="{StaticResource ImageButton}"
                                            Click="CloseButtonClick"

                                        >
                                        <Image Source="{StaticResource App_Close}" />
                                    </Button>
                                </Grid>
                            </Border>
                            <ContentPresenter />
                        </DockPanel>
                    </Border>
                    <Line
                        MouseDown="OnSizeNorth"
                        x:Name="lnSizeNorth"
                        Stroke="Transparent"   
                        Cursor="SizeNS"
                        X1="1" X2="{TemplateBinding ActualWidth}" Y1="1" Y2="1"
                        StrokeThickness="3"
                        />
                    <Line
                        MouseDown="OnSizeSouth"
                        x:Name="lnSizeSouth"
                        Stroke="Transparent"
                        VerticalAlignment="Bottom" 
                        Cursor="SizeNS"
                        X1="1" X2="{TemplateBinding ActualWidth}" Y1="{TemplateBinding ActualHeight}" Y2="{TemplateBinding ActualHeight}"
                        StrokeThickness="3"
                        />
                    <Line
                        MouseDown="OnSizeWest"
                        x:Name="lnSizeWest"
                        Stroke="Transparent"
                        Cursor="SizeWE"
                        X1="1" X2="1" Y1="1" Y2="{TemplateBinding ActualHeight}"
                        StrokeThickness="3"
                        />
                    <Line
                        MouseDown="OnSizeEast"
                        x:Name="lnSizeEast"
                        Stroke="Transparent"
                        HorizontalAlignment="Right" 
                        Cursor="SizeWE"
                        X1="{TemplateBinding ActualWidth}" X2="{TemplateBinding ActualWidth}" Y1="1" Y2="{TemplateBinding ActualHeight}"
                        StrokeThickness="3"
                        />
                    <Rectangle MouseDown="OnSizeNorthWest" x:Name="rectSizeNorthWest" Cursor="SizeNWSE" Fill="Transparent" Width="5" Height="5" VerticalAlignment="Top" HorizontalAlignment="Left" />
                    <Rectangle MouseDown="OnSizeNorthEast" x:Name="rectSizeNorthEast" Cursor="SizeNESW" Fill="Transparent" Width="5" Height="5" VerticalAlignment="Top" HorizontalAlignment="Right" />
                    <Rectangle MouseDown="OnSizeSouthWest" x:Name="rectSizeSouthWest" Cursor="SizeNESW" Fill="Transparent" Width="5" Height="5" VerticalAlignment="Bottom" HorizontalAlignment="Left" />
                    <Rectangle MouseDown="OnSizeSouthEast" x:Name="rectSizeSouthEast" Cursor="SizeNWSE" Fill="Transparent" Width="5" Height="5" VerticalAlignment="Bottom" HorizontalAlignment="Right" />
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="WindowState" Value="Maximized">
                        <Setter TargetName="MaxButtonImage" Property="Source" Value="{StaticResource App_Maximize}"/>
                    </Trigger>
                    <Trigger Property="IsActive" Value="False">
                        <Setter TargetName="PART_Border" Property="BorderBrush" Value="{StaticResource WindowBorderBrushInactive}"/>
                    </Trigger>
                    <Trigger Property="ResizeMode" Value="NoResize">
                        <Setter TargetName="MinButton" Property="Visibility" Value="Hidden"/>
                        <Setter TargetName="MaxButton" Property="Visibility" Value="Hidden"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Resources>
        <Style TargetType="{x:Type StatusBar}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsActive, RelativeSource={RelativeSource AncestorType=Window}}" Value="True">
                    <Setter Property="Foreground" Value="{StaticResource WindowStatusForeground}" />
                    <Setter Property="Background" Value="{StaticResource WindowBorderBrush}" />
                </DataTrigger>
                <DataTrigger Binding="{Binding IsActive, RelativeSource={RelativeSource AncestorType=Window}}" Value="False">
                    <Setter Property="Foreground" Value="{StaticResource WindowStatusForegroundInactive}" />
                    <Setter Property="Background" Value="{StaticResource WindowBorderBrushInactive}" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Style.Resources>
</Style>

Solution

  • It looks like the problem you are having is that the content does not have a size, so it is taking the maximum available space, for me it sets the width to the combined width of my two screens.

    You basically have a situation where the window is saying "I'll take as much as you need Content" and the Content is saying "I'll have as much as you give me Window", so the Window is just taking it all.

    Edit: Actually, if you are to remove the margin on the containing grid and then remove the lines with their ActualHeight/Width bindings then it will fix your issue. Looks these two aspects of your template are pushing the size out until it reaches the maximum.