WPF styles and grid layout issues - wpf

RESOLVED EDIT:
Because it is not clear through the discussion nothing was really wrong with the structure of the grids or their placement. The designer however misrepresented where the grid was. For some reason it placed the grid in the upper left hand corner of the window rather then within the content portion of the window. Once that is accounted for everything else lined up as anticipated.
I am working on a WPF project and have run into an issue with styling my forms. I needed a custom window, one without all the windows stuff; so I created a custom window style that I could apply to all my windows. Within that style I created a grid so that I could more easily place the default elements of the default window style. Then on my dashboard window I apply the default window style and all looks well. But once I attempt to place a grid within the dashboard window things start getting wonky.
In order to compensate for this I added an Adorner Decorator to the grid in the default style and placed it at the content location of that grid. This does allow me to place my content within dashboard window, but it does not follow the grid rules made by the dashboards grid.
So all I am attempting to do is create a custom window style that can be applied to all of my windows, and be able to use a grid to slice up the area designated contented by that windows default style.
This is the meaningful portion of the windows style, it lays out a grid for the boarders(drag labels), header, footer, control bar buttons(max, min, close) and content.
<Style x:Key="DefaultWindowStyle" TargetType="{x:Type Window}" >
<Setter Property="Margin" Value="5" />
<Setter Property="ResizeMode" Value="NoResize" />
<Setter Property="WindowStyle" Value="None" />
<Setter Property="Background" Value="MidnightBlue" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Grid Name="WindowGrid">
<Grid.RowDefinitions>
<RowDefinition Name="TopBorderRow" Height="5" />
<RowDefinition Name="TitleBarRow" Height="30" />
<RowDefinition Name="RContentRow" Height="*" />
<RowDefinition Name="BottomBorderRow" Height="5" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Name="LeftBorderCol" Width="5" />
<ColumnDefinition Name="CContentCol" Width="*" />
<ColumnDefinition Width="30" />
<ColumnDefinition Width="30" />
<ColumnDefinition Width="30" />
<ColumnDefinition Name="RightBorderCol" Width="5" />
</Grid.ColumnDefinitions>
<s:ResizeThumb Style="{StaticResource ThumbAsBorderStyle}" Height="5" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="6" Cursor="SizeNS" HorizontalAlignment="Stretch" VerticalAlignment="Top" />
<s:ResizeThumb Style="{StaticResource ThumbAsBorderStyle}" Height="5" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="6" Cursor="SizeNS" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" />
<s:ResizeThumb Style="{StaticResource ThumbAsBorderStyle}" Width="5" Grid.Row="0" Grid.Column="0" Grid.RowSpan="4" Cursor="SizeWE" HorizontalAlignment="Left" VerticalAlignment="Stretch" />
<s:ResizeThumb Style="{StaticResource ThumbAsBorderStyle}" Width="5" Grid.Row="0" Grid.Column="5" Grid.RowSpan="4" Cursor="SizeWE" HorizontalAlignment="Right" VerticalAlignment="Stretch" />
<s:ResizeThumb Style="{StaticResource ThumbAsBorderStyle}" Height="5" Width="5" Grid.Row="0" Grid.Column="0" Cursor="SizeNWSE" HorizontalAlignment="Left" VerticalAlignment="Top" />
<s:ResizeThumb Style="{StaticResource ThumbAsBorderStyle}" Height="5" Width="5" Grid.Row="0" Grid.Column="5" Cursor="SizeNESW" HorizontalAlignment="Right" VerticalAlignment="Top" />
<s:ResizeThumb Style="{StaticResource ThumbAsBorderStyle}" Height="5" Width="5" Grid.Row="3" Grid.Column="0" Cursor="SizeNESW" HorizontalAlignment="Left" VerticalAlignment="Bottom" />
<s:ResizeThumb Style="{StaticResource ThumbAsBorderStyle}" Height="5" Width="5" Grid.Row="3" Grid.Column="5" Cursor="SizeNWSE" HorizontalAlignment="Right" VerticalAlignment="Bottom" />
<s:DragLabel Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="6" Style="{DynamicResource DefaultWindowTitle}" Content="{TemplateBinding Title}"/>
<s:TitleBarButton x:Name="Minimize" Style="{StaticResource TitleBarButton}" Grid.Row="1" Grid.Column="2">
<Image>
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="{DynamicResource ButtonMinimize}" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Source" Value="{DynamicResource ButtonMinimizeHover}"/>
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</s:TitleBarButton>
<s:TitleBarButton x:Name="Maximize" Style="{StaticResource TitleBarButton}" Grid.Row="1" Grid.Column="3">
<Image>
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="{DynamicResource ButtonMaximize}" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Source" Value="{DynamicResource ButtonMaximizeHover}"/>
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</s:TitleBarButton>
<s:TitleBarButton x:Name="Close" Style="{StaticResource TitleBarButton}" Grid.Row="1" Grid.Column="4">
<Image>
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="{DynamicResource ButtonClose}" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Source" Value="{DynamicResource ButtonCloseHover}"/>
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</s:TitleBarButton>
<AdornerDecorator Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="4">
<ContentPresenter />
</AdornerDecorator>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And here is the code of the dashboard window where I am attempting to place fitted elements in their correct grid slots (those created by the dashboard window). The grid created blow looks as though all of the rows and columns are in the right spot, and their elements should simply fit, but they have strange margins. So the StudySessionPanel(which is 128x234) should fit perfectly within row 1, col 2, but as you can see it require colsaps, margins and other junk in order to place it at the correct location.
Title="Dashboard"
Style="{DynamicResource DefaultWindowStyle}" mc:Ignorable="d"
Height="840" Width="1024">
<Grid Name="DashboardGrid" Width="1024" Height="840">
<Grid.RowDefinitions>
<RowDefinition Height="63" />
<RowDefinition Height="128" />
<RowDefinition Height="234" />
<RowDefinition Height="18"/>
<RowDefinition Height="380" />
<RowDefinition Height="16" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16" />
<ColumnDefinition Width="15.25" />
<ColumnDefinition Width="234" />
<ColumnDefinition Width="15.25" />
<ColumnDefinition Width="280" />
<ColumnDefinition Width="15.25" />
<ColumnDefinition Width="417" />
<ColumnDefinition Width="15.25" />
<ColumnDefinition Width="16" />
</Grid.ColumnDefinitions>
<cc:PanelStudySession x:Name="StudySessionPanel" Grid.ColumnSpan="3" Margin="15,66,16,62" Grid.RowSpan="2" Grid.Row="1">
</cc:PanelStudySession>
<cc:PanelPerformance x:Name="PerformancePanel" Grid.Column="3" Grid.ColumnSpan="4" Margin="0,66,10,62" Grid.Row="1" Grid.RowSpan="2">
</cc:PanelPerformance>
<cc:PanelProgress x:Name="ProgressPanel" Grid.Column="1" Grid.ColumnSpan="4" Margin="0,190,10,62" Grid.Row="2" Grid.RowSpan="3">
</cc:PanelProgress>
<cc:PanelHistory x:Name="HistoryPanel" Grid.Column="5" Grid.ColumnSpan="2" Margin="0,190,15,62" Grid.Row="2" Grid.RowSpan="3">
</cc:PanelHistory>
</Grid>
This is the image with the margins, and row/col spans
Ignoring the designer the elements sort of line up, though some of them get chopped. It looks the same when ran as it does in the presenter.

Your StudySessionPanel is actually being put in rows 1-2 (Row=1, RowSpan=2) and columns 0-2 (no column and ColumnSpan=3). Just set Grid.Row and Grid.Column if you want to put it in a cell.

Related

Why doesn't my grid grow when I enlarge the program?

So my code looks like this:
<Window.Resources>
<Style x:Key="ButtonTemplate" TargetType="Button">
<Setter Property="Background" Value="{x:Null}"/>
<Setter Property="BorderBrush" Value="{x:Null}"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}" BorderBrush="Black" BorderThickness="0">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<DockPanel VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Border Background="#FFFFFF" BorderThickness="0 0 0 1" BorderBrush="Black" VerticalAlignment="Top" DockPanel.Dock="Top" Width="1009" Height="30">
<Grid HorizontalAlignment="Right">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" x:Name="btnToolbarMin" Content="─" Height="30" Width="44" Style="{StaticResource ButtonTempplate}" Click="btnToolbarMin_Click"/>
<Button Grid.Column="1" x:Name="btnToolbarMax" Content="£" FontFamily="Wingdings 2" Height="30" Width="44" Style="{StaticResource ButtonTempplate}" Click="btnToolbarMax_Click" />
<Button Grid.Column="2" x:Name="btnToolbarClose" Content="Ñ" FontFamily="Wingdings 2" Height="30" Width="44" Style="{StaticResource ButtonTempplate}" Click="btnToolbarClose_Click" />
</Grid>
</Border>
<StackPanel Background="#F5F5F5" Height="70" DockPanel.Dock="Top" VerticalAlignment="Top">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="336*"/>
<ColumnDefinition Width="627*"/>
<ColumnDefinition Width="46*"/>
</Grid.ColumnDefinitions>
<Label Margin="13 10 0 0" FontWeight="Bold" Content="Artikel" FontFamily="Arial" FontSize="15" Foreground="#38C72E" Grid.Row="0" HorizontalAlignment="Left" Width="58"/>
<Menu Grid.Row="1" Background="#F5F5F5" Margin="13,0,282,11" >
<MenuItem Header="≡" FontWeight="Bold" FontSize="15">
<MenuItem Header="WW" FontSize="10"/>
</MenuItem>
</Menu>
<Button Content="↻" FontSize="15" FontFamily="Lucida Sans Unicode" Background="{x:Null}" BorderThickness="0" Grid.Column="1" HorizontalAlignment="Right" Width="42"/>
<Button Content="­☼" FontSize="15" Background="{x:Null}" BorderThickness="0" Grid.Column="2" HorizontalAlignment="Right" Width="43"/>
</Grid>
</StackPanel>
<StackPanel Background="#F5F5F5" VerticalAlignment="Bottom" Height="40">
<Grid HorizontalAlignment="Right">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button Content="Dummy1" Grid.Column="1" Height="25" Width="115" HorizontalAlignment="Right" Margin="5 10 13 0"/>
<Button Content="Dummy2" Grid.Column="0" Height="25" Width="115" HorizontalAlignment="Right" Margin="0 10 0 0"/>
</Grid>
</StackPanel>
</DockPanel>
</Grid>
And when I press the max button (i.e. the one next to the close button) with this code:
this.WindowState = WindowState.Maximized;
Then he lets several things grow with it, but some things like the top bar, for example, where the 3 buttons are to close, minimize and not grow with them, why is that? I also worked with dock panel and horizontal and vertical alignment, but to no avail.
I think the issue is that you set the Width of the top bar explicitly, which leads to the bar not being shown when the window is small and being centered when the window is larger that size.
<Border ... Width="1009" ...>
The same applies to the explicit Height="30" in the Border. The height is fixed, so of course it does not scale with the window.

Custom border for UserControl

I know too little about design to pull this off.
I am trying to make a UserControl with a special border. The border should look like this:
The header is a label (or textblock if is a must) with the content set at init time.
The border must stop before the header and start again after the header with a margin like described.
The border will house a frame or grid which must confrom to the border shape (probably with a mask) The entire background must be transparent or alpha-ed (Color #000000XX) which is important because the header cant just "hide" the rectangle by being on top.
I'd appreciate directions to achieve this. Blend from visual studio 2012 is available.
Thank you
here you go
I made use of HeaderedContentControl which allows you to have a header and a content which you can further use in a template of your preference
<HeaderedContentControl x:Class="CSharpWPF.MyUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="300"
Header="Header">
<HeaderedContentControl.Template>
<ControlTemplate TargetType="HeaderedContentControl">
<Grid>
<Border BorderBrush="Black"
BorderThickness="4"
CornerRadius="10"
Padding="4"
Margin="10">
<ContentPresenter />
</Border>
<TextBlock Text="{TemplateBinding Header}"
Background="White"
HorizontalAlignment="Left"
VerticalAlignment="Top"
FontSize="13"
Margin="25,0,0,0"
Padding="10,0"/>
</Grid>
</ControlTemplate>
</HeaderedContentControl.Template>
<Grid>
<TextBlock Text="content" />
</Grid>
</HeaderedContentControl>
result
Update
try this template, I did try to achieve by pure xaml
<HeaderedContentControl.Template>
<ControlTemplate TargetType="HeaderedContentControl">
<DockPanel x:Name="root"
LastChildFill="True"
Margin="10">
<DockPanel.Resources>
<Style TargetType="Border">
<Setter Property="BorderBrush"
Value="Black" />
<Setter Property="Width"
Value="30" />
<Setter Property="Height"
Value="30" />
<Setter Property="CornerRadius"
Value="10" />
</Style>
</DockPanel.Resources>
<Grid DockPanel.Dock="Top"
Height="20">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<Border BorderThickness="4,4,0,0" />
<Border BorderThickness="0,4,0,0"
Grid.Column="2"
Width="auto"
CornerRadius="0" />
<Border BorderThickness="0,4,4,0"
Grid.Column="3"
HorizontalAlignment="Right" />
<TextBlock Text="{TemplateBinding Header}"
FontSize="13"
Grid.Column="1"
Margin="10,-10"
VerticalAlignment="Top" />
</Grid>
<Grid Height="20"
DockPanel.Dock="Bottom">
<Border BorderThickness="4,0,4,4"
Width="auto"
VerticalAlignment="Bottom" />
</Grid>
<Border BorderThickness="4,0,0,0"
DockPanel.Dock="Left"
Height="auto"
Width="20"
CornerRadius="0" />
<Border BorderThickness="0,0,4,0"
DockPanel.Dock="Right"
Width="20"
Height="auto"
CornerRadius="0" />
<ContentPresenter Margin="-10" />
</DockPanel>
</ControlTemplate>
</HeaderedContentControl.Template>
other approach might include some code behind if this is not suitable
result

DataTrigger in ControlTemplate does not work

I am new here and hope my first question meets stack overflow's requirements. I have done some research so far but could not figure it out myself.
I create a UserControl (derived from an intermediate base Class) which should be able to change a color sign to a different color depending on its "VisualAlarmState" Property which is a DependencyProperty.
The Style plus ControlTemplate are rendered as expected but the DataTrigger at the end of the style does not change the color (=image) of VisualAlarmSign which is an Image element.
The code can be compiled and run without errors but the alarm state will not be shown as expected.
Something I do ot really understand either: I have to reference the Style dynamically because Style="{StaticResource DashboardItemStyle}" will be underlinded and at mouse hover says: "The resource "DashboardItemStyle" could not be resolved."
<ucbase:DashboardItemBase.Resources>
<BitmapImage x:Key="MO-Zylinderdeckel" UriSource="/ModuleDashboard;component/Resources/MO-Zylinderdeckel.tif" />
<BitmapImage x:Key="MO-Zylindermantel" UriSource="/ModuleDashboard;component/Resources/MO-Zylindermantel.tif" />
<BitmapImage x:Key="MO-Zylinderboden" UriSource="/ModuleDashboard;component/Resources/MO-Zylinderboden.tif" />
<BitmapImage x:Key="MO-Marker-Grün" UriSource="/ModuleDashboard;component/Resources/MO-Marker-Grün.tif" />
<BitmapImage x:Key="MO-Marker-Orange" UriSource="/ModuleDashboard;component/Resources/MO-Marker-Orange.tif" />
<BitmapImage x:Key="MO-Marker-Rot" UriSource="/ModuleDashboard;component/Resources/MO-Marker-Rot.tif" />
<Style x:Key="DashboardItemStyle" TargetType="{x:Type ucbase:DashboardItemBase}">
<Setter Property="Template" x:Name="Template1">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ucbase:DashboardItemBase}">
<dxlc:Tile x:Name="Tile" Grid.Column="0" Grid.ColumnSpan="1" Grid.Row="0" Grid.RowSpan="1"
Height="128.5" Width="208.5" Background="{x:Null}">
<dxlc:Tile.Content>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="11.5" />
<RowDefinition Height="*" />
<RowDefinition Height="12.5" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="6.5" />
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Grid.ColumnSpan="1" Grid.Row="0" Grid.RowSpan="1"
HorizontalAlignment="Stretch" Stretch="Fill" VerticalAlignment="Stretch"
Source="{StaticResource MO-Zylinderdeckel}" />
<Grid Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" Grid.RowSpan="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="6.5" />
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Grid.ColumnSpan="1" Grid.Row="1" Grid.RowSpan="2"
HorizontalAlignment="Stretch" Stretch="Fill" VerticalAlignment="Stretch"
Source="{StaticResource MO-Zylindermantel}" />
<Image x:Name="VisualAlarmSign" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" Height="14"
Margin="0,20,0,0" Width="19.5" HorizontalAlignment="Right"
VerticalAlignment="Top" Source="{StaticResource MO-Marker-Grün}" />
</Grid>
<Image Grid.Column="0" Grid.ColumnSpan="1" Grid.Row="3" Grid.RowSpan="1"
HorizontalAlignment="Stretch" Stretch="Fill" VerticalAlignment="Stretch"
Source="{StaticResource MO-Zylinderboden}" />
</Grid>
</dxlc:Tile.Content>
</dxlc:Tile>
<ControlTemplate.Triggers>
<!-- This Trigger has no effect. Why?-->
<DataTrigger
Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=VisualAlarmState}">
<DataTrigger.Value>
<vmbase:AlarmState>Alarm</vmbase:AlarmState>
</DataTrigger.Value>
<Setter TargetName="VisualAlarmSign" Property="Source"
Value="{StaticResource MO-Marker-Rot}" />
</DataTrigger> </ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ucbase:DashboardItemBase.Resources>
Working Solution
I removed Source={StaticResource MO-Marker-Grün} from the <Image> element and I moved the <DataTrigger> from <ControlTemplate.Triggers> to <Style.Triggers> in <Image.Style> which resulted in the following XAML code:
<ucbase:DashboardItemBase.Resources>
...
<BitmapImage x:Key="MO-Marker-Rot" UriSource="/ModuleDashboard;component/Resources/MO-Marker-Rot.tif" />
...
<Style x:Key="DashboardItemStyle" TargetType="{x:Type ucbase:DashboardItemBase}">
<Setter Property="Template" x:Name="Template1">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ucbase:DashboardItemBase}">
<dxlc:Tile x:Name="Tile" Grid.Column="0" Grid.ColumnSpan="1" Grid.Row="0" Grid.RowSpan="1"
Height="128.5" Width="208.5" Background="{x:Null}">
<dxlc:Tile.Content>
<Grid>
...
<Image x:Name="VisualAlarmSign" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0"
Height="14" Margin="0,20,0,0" Width="19.5" HorizontalAlignment="Right"
VerticalAlignment="Top" >
<Image.Style>
<Style>
<Style.Triggers>
<DataTrigger
Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=VisualAlarmState}"
Value="Alarm">
<Setter Property="Image.Source"
Value="{StaticResource MO-Marker-Rot}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
...
</Grid>
</dxlc:Tile.Content>
</dxlc:Tile>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ucbase:DashboardItemBase.Resources>
Try setting the source of image using style property setter. Some how trigger behave wired.
<Image x:Name="VisualAlarmSign" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" Height="14"
Margin="0,20,0,0" Width="19.5" HorizontalAlignment="Right"
VerticalAlignment="Top">
<Image.Style>
<Style>
<Setter TargetName="VisualAlarmSign" Property="Source"
Value="{StaticResource MO-Marker-Grün}" />
</Style>
</Image.Style>
</Image>
Make sure to remove the source property in the image tag.
Some how triggers may not set properties we have used in the tag. in your case you set the value of source in the image tag. if you set the same value through style setter it may worm. its worth a try.

WPF Button Style Doesn't Show Text

I'm new to this so please bear with me.
I now have this Style. Paste this into a window to see it in action.
<Window.Resources>
<Style x:Key="SelectionButton3"
TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ClipToBounds="False">
<Grid.RowDefinitions>
<RowDefinition Height="75" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="55" />
</Grid.ColumnDefinitions>
<Border x:Name="TheBorder"
BorderThickness="0,1.5,1.5,1.5"
CornerRadius="3"
Background="SteelBlue"
Height="35"
Grid.Column="1"
Grid.Row="0"
Margin="-31"
BorderBrush="DarkSlateBlue"/>
<Rectangle Name="TheRectangle"
Fill="SteelBlue"
Stroke="DarkSlateBlue"
Grid.Row="0"
Grid.Column="0">
<Rectangle.LayoutTransform>
<RotateTransform Angle="-45" />
</Rectangle.LayoutTransform>
<Rectangle.BitmapEffect>
<DropShadowBitmapEffect ShadowDepth="5" />
</Rectangle.BitmapEffect>
</Rectangle>
<ContentPresenter x:Name="ContentArea"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Content="{Binding Path=Content, RelativeSource={RelativeSource TemplatedParent}}" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter TargetName="TheBorder"
Property="BitmapEffect">
<Setter.Value>
<DropShadowBitmapEffect ShadowDepth="0" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Foreground"
Value="White"/>
<Setter Property="FontFamily"
Value="Segoe UI" />
<Setter Property="FontSize"
Value="20" />
</Style>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="250" />
</Grid.ColumnDefinitions>
<Button Grid.Row="1"
Grid.Column="1"
Style="{StaticResource SelectionButton3}"
Margin="0,0,0,5"
Click="Button_Click">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image Height="35"
Width="35"
Stretch="Fill"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Grid.Column="0"
Margin="32.5,0,0,0"
Source="/app;component/Media/Images/Mail/email.png" />
<TextBlock Text="Email"
Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="22,0,0,0"/>
</Grid>
</Button>
I have 2 questions:
1) Why is only part of the text showing up?
2) How do I put the Image and TextBlock in the Template and just bind to them?
The reason why your Text is clipped is because you did not specify Grid.Row and Grid.Column for your ContentPresenter. This causes your button's content to default to the 0th Row and 0th Column on your ControlTemplate, which in combination with your margins and positions causes the Textblock on your Button Element to be cut off. I am guessing this might be your intent?
<ContentPresenter x:Name="ContentArea"
Grid.Column="0"
Grid.ColumnSpan="2"
Grid.Row="0"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Content="{Binding Path=Content,
RelativeSource={RelativeSourceTemplatedParent}}" />
Now the ContentPresenter will span both columns on the ControlTemplate's Grid, so your Textblock will have more room to display itself.
To answer your second question How do I put the Image and Textblock in the template and just bind to them?
One way to do it is to subclass the Button class, call it MyImageButton for example, and implement two new Dependency Properties called Image and Text in this new class. Then you can move your <Image> and <TextBlock> into your Control Template and bind them to your new Image and Text Properties. You can then instantiate MyImageButton and used the new Properties to set the button's image and text.

WPF Events in ResourceDictionary for a ControlTemplate

I'm currently trying to implement a Metro styled Window.
So i've made the following styles inside a ResourceDictionary:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Brushes -->
<SolidColorBrush x:Key="BackgroundColor" Color="#FFFFFFFF" />
<!-- Buttons -->
<Style x:Key="MetroControlBoxButton" TargetType="Button">
<Setter Property="Background" Value="{StaticResource BackgroundColor}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Windows -->
<Style x:Key="MetroWindow" TargetType="Window">
<Setter Property="UseLayoutRounding" Value="True" />
<Setter Property="WindowStyle" Value="None" />
<Setter Property="ResizeMode" Value="NoResize" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Window">
<Grid Background="{StaticResource BackgroundColor}">
<Grid.RowDefinitions>
<RowDefinition Height="6" />
<RowDefinition Height="24" />
<RowDefinition Height="*" />
<RowDefinition Height="24" />
<RowDefinition Height="6" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="6" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="6" />
</Grid.ColumnDefinitions>
<Rectangle Name="topLeftBorderRectangle" Fill="Red" Grid.Row="0" Grid.Column="0" />
<Rectangle Name="topCenterBorderRectangle" Fill="Orange" Grid.Row="0" Grid.Column="1" />
<Rectangle Name="topRightBorderRectangle" Fill="Red" Grid.Row="0" Grid.Column="2" />
<Rectangle Name="middleLeftBorderRectangle" Fill="Orange" Grid.Row="1" Grid.RowSpan="3" Grid.Column="0" />
<Rectangle Name="middleRightBorderRectangle" Fill="Orange" Grid.Row="1" Grid.RowSpan="3" Grid.Column="2" />
<Rectangle Name="bottomLeftBorderRectangle" Fill="Red" Grid.Row="4" Grid.Column="0" />
<Rectangle Name="bottomCenterBorderRectangle" Fill="Orange" Grid.Row="4" Grid.Column="1" />
<Rectangle Name="bottomRightBorderRectangle" Fill="Red" Grid.Row="4" Grid.Column="2" />
<Rectangle Name="statusBarRectangle" Fill="Yellow" Grid.Row="3" Grid.Column="1" />
<Grid Grid.Row="1" Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="28" />
<ColumnDefinition Width="28" />
<ColumnDefinition Width="28" />
</Grid.ColumnDefinitions>
<Rectangle Name="dragRectangle" Fill="Yellow" Grid.Row="0" Grid.Column="1" />
<Button Name="minimizeButton" Content="_" Grid.Row="0" Grid.Column="2" Style="{StaticResource MetroControlBoxButton}" Command="{Binding Path=DataContext.MinimizeCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" />
<Button Name="maximizeButton" Content="[]" Grid.Row="0" Grid.Column="3" Style="{StaticResource MetroControlBoxButton}" Command="{Binding Path=DataContext.MaximizeNormalizeCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" />
<Button Name="closeButton" Content="X" Grid.Row="0" Grid.Column="4" Style="{StaticResource MetroControlBoxButton}" Command="{Binding Path=DataContext.CloseCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" />
</Grid>
<ContentPresenter Grid.Row="2" Grid.Column="1" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
My problem is that i have no idea how to implement de drag feature.
My dragRectangle doesn't have a Command property so how can i call DragMove() on MouseLeftButtonDown on a Rectangle using MVVM?
Thanks
A ResourceDictionary can have code behind just like Windows etc. so you could add an event handler and call DragMove from there
Setting up the code behind requires a couple of steps.
If your ResourceDictionary is called MetroStyleResourceDictionary.xaml you add a new file in Visual Studio in the same folder called MetroStyleResourceDictionary.xaml.cs
The code behind file should then look like this
public partial class MetroStyleResourceDictionary
{
//...
}
After that you need to add the x:Class attribute to the Xaml file
<ResourceDictionary x:Class="YourNamespace.MetroStyleResourceDictionary"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!--...-->
</ResourceDictionary>
Now you can add an event handler to the dragRectangle for MouseLeftButtonDown. You'll also need to get a hold of the Window so binding that to Tag might be a good idea
<Rectangle Name="dragRectangle"
MouseLeftButtonDown="dragRectangle_MouseLeftButtonDown"
Tag="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
.../>
And finally you can add the event handler to the code behind file which will look like this
public partial class MetroStyleResourceDictionary
{
void dragRectangle_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
Rectangle dragRectangle = sender as Rectangle;
Window window = dragRectangle.Tag as Window;
if (window != null)
{
window.DragMove();
}
}
}

Resources