WPF Window Chrome styling - wpf

I'm using WindowChrome class for solving problem with different icons in task bar and app header. Here is my window.style example:
<Window.Style>
<Style TargetType="{x:Type local:MainWindow}">
<Setter Property="shell:WindowChrome.WindowChrome">
<Setter.Value>
<shell:WindowChrome GlassFrameThickness="-1"
ResizeBorderThickness="4"
UseAeroCaptionButtons="True"/>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MainWindow}">
<Grid>
<!-- This is the ContentPresenter that displays the window content. -->
<Border Margin="1 30 1 1" Background="White"
>
<ContentPresenter Content="{TemplateBinding Content}" />
</Border>
<!-- Window Title -->
<Image Margin="5" VerticalAlignment="Top" HorizontalAlignment="Left" Width="16" Height="16" Source="some.ico"></Image>
<TextBlock Margin="25 5 0 0" VerticalAlignment="Top" TextAlignment="Left"
Text="{Binding RelativeSource=
{RelativeSource TemplatedParent}, Path=Title}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Style>
When not maximized - my window looks as I want.
But when maximized(by double click/maximize button click or dock to the top) the header background is black, I can't see any buttons and my icon is out of the screen bounds. :(
Any suggestions? What i'm doing wrong in my style?

Related

How to define a TabItem Header Template in WPF

I'm learning WPF and I read an article about Templating. So I wanted to write some code, but i got stuck.
What do I want to do? My Application has A TabControl and I want that all the tabs has the same Layout. A stackpanel and in the stackpanel an Image and a Textblock.
Now i don't know how the content can be set afterwards. Do I need a ContentPresenter?
<ControlTemplate x:Key="TabTemplate">
<StackPanel Orientation="Horizontal">
<Image></Image>
<TextBlock></TextBlock>
</StackPanel>
</ControlTemplate>
In your resource dictionary add a Style with your desired template:
<Style x:Key="CustomTabItemStyle"
TargetType="{x:Type TabItem}">
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid x:Name="Root"
Width="180"
Height="45"
Margin="0,0,0,0"
SnapsToDevicePixels="true">
<StackPanel Orientation="Horizontal">
<Image Width="90"
Margin="10"
VerticalAlignment="Center"
Source="pack://Application:,,,/img/myTabImage.png"
Stretch="Uniform" />
<TextBlock x:Name="contentPresenter"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Focusable="False"
FontSize="16"
Foreground="White"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Text="{TemplateBinding Header}" />
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Don't forget to edit your Image. If all tabs has same image then just change a Source link, otherwise, you may need another binding, e.g Content.
And then simply use this style in your TabItems:
<TabControl Margin="0,5,0,0"
FocusVisualStyle="{x:Null}">
<TabItem Header="My First Tab"
IsSelected="{Binding FirstTabItemSelected}"
Style="{DynamicResource CustomTabItemStyle}">
...
</TabItem>
<TabItem Header="My Second Tab"
IsSelected="{Binding SecondTabItemSelected}"
Style="{DynamicResource CustomTabItemStyle}">
...
</TabItem>
</TabControl>

How can I bring a Button in a custom control "to the front"?

In a custom control I have as the content a stackpanel (horizontal) en in it, a Textblock and a Button.
The custom control works and the result is a rectangle which is my local:DropDownToggleButton.
This reactangle is divided into two sub-rectangles: on to the left is just the <TextBlock Text="Test"part and to the right is the button <Button x:Name="ButtonTest which is stretched to fill the height of the rectangle.
However when I click in the upper-right part of the rectangle, the local:DropDownToggleButton itself receives the event and not the button that is also present there. It is as if the Button only responds to mouse events received by the Textblock in the content of the button. How can I make the whole area of the button responsive to mouse clicks?
The custom control reacts on the Clicked or PreviewMouseDown event of the button. Both events have the same problem. Also adding Panel.ZIndex="1"doesn't help.
<local:DropDownToggleButton ToolTip="Show" DropDownButton="{Binding ElementName=ButtonTest}"
VerticalAlignment="Stretch" VerticalContentAlignment="Stretch" Padding="0" BorderThickness="0"
Style="{StaticResource {x:Static ToolBar.ToggleButtonStyleKey}}">
<local:DropDownToggleButton.DropDownMenu>
<ContextMenu>
<ContextMenu.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Background="WhiteSmoke"></StackPanel>
</ItemsPanelTemplate>
</ContextMenu.ItemsPanel>
<ContextMenu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<TextBlock Padding="6" Text="{TemplateBinding Header}" Background="{TemplateBinding Background}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Margin" Value="0"/>
<Style.Triggers>
<Trigger Property="TextBlock.IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource mouseover}"/>
</Trigger>
</Style.Triggers>
</Style>
</ContextMenu.ItemContainerStyle>
<MenuItem Header="Test 1" />
<MenuItem Header="Test 2"/>
</ContextMenu>
</local:DropDownToggleButton.DropDownMenu>
<StackPanel Orientation="Horizontal" VerticalAlignment="Stretch">
<TextBlock Text="Test" VerticalAlignment="Center"/>
<Button x:Name="ButtonTest" ToolTip="Other" Padding="0" Margin="0" VerticalContentAlignment="Stretch" VerticalAlignment="Stretch">
<Button.Template>
<ControlTemplate TargetType="Button">
<ContentPresenter/>
</ControlTemplate>
</Button.Template>
<TextBlock FontSize="16" FontFamily="Marlett" Text="6" VerticalAlignment="Center" />
</Button>
</StackPanel>
</local:DropDownToggleButton>
The reason the button does not react is because you have taken away most of what you would expect a button to have, your button template is just the ContentPresenter, so the button is literally only the textblock. Try
<ControlTemplate TargetType="Button">
<Border Background="Transparent">
<ContentPresenter/>
</Border>
</ControlTemplate>

Reading Content property of a Button into a ConrtolTemplate in a style

I have a style for a button with a ControlTemplate something like this
<Style x:Key="ButtonStyle"
BasedOn="{x:Null}"
TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Rectangle x:Name="rectangle"
Fill="#FF04822A"
Stroke="{x:Null}" />
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="Heavy"
Foreground="Black"
x:Name="btnText"
TextAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Button Grid.Row="3"
Grid.Column="5"
Margin="4,0,4,0"
Command="{Binding ResetCommand}"
Content ="Reset Cells"
Style="{StaticResource ButtonStyle}" />
I want the TextBlock to read from the button Content every time its updated.
Add a template binding to the TextBlock:
Text="{TemplateBinding Content}"
You might just want to use a ContentPresenter instead though (as TextBlocks usually only display text).

Stuck on button template with texbox

I have a button template shown bellow, in this case when the text is entered the button stays the same size, and it works ok. However I want just a border, so when I try to add that ellipse inside the thumb to get the border, and try typing text in the textbox, when the text becomes larger than the button suddenly it covers the button with a white background, i don't know why this is happening, any help would be appreciated.
<Window.Resources>
<Style TargetType="{x:Type Thumb}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Thumb">
<Ellipse Fill="{TemplateBinding Background}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Thumb x:Name="outerThumbResize" Cursor="SizeNESW" Background="Red" Height="50" Width="50"/>
<!--<Ellipse x:Name="innerCircle" Fill="White" RenderTransformOrigin=".5,.5">
<Ellipse.RenderTransform>
<ScaleTransform ScaleX=".8" ScaleY=".8"/>
</Ellipse.RenderTransform>
</Ellipse>-->
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBox x:Name="textBox" Background="Transparent" BorderThickness="0" Visibility="Collapsed" TextAlignment="Center" PreviewKeyUp="textBox_PreviewKeyUp" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Thumb x:Name="innerThumb" Background="Transparent" DragDelta="nodeThumb_DragDelta" RenderTransformOrigin=".5,.5">
<Thumb.RenderTransform>
<ScaleTransform ScaleX=".9" ScaleY=".9"/>
</Thumb.RenderTransform>
</Thumb>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
i solved it using the stroke thickness of the ellipse in the template.

Setting tooltip to equal content

I'm trying to set a data grid's cell's tooltip to be equal to the text inside of a TextBlock in that cell. What I have so far is this:
<Style x:Key="CellStyle" TargetType="{x:Type DataGridCell}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridCell">
<Grid>
<TextBlock Margin="2" VerticalAlignment="Center"
HorizontalAlignment="Left" TextWrapping="Wrap" >
<ContentPresenter Content="{TemplateBinding Property=ContentControl.Content}" />
<TextBlock.ToolTip>
<ContentPresenter Content="{TemplateBinding Property=ContentControl.Content}" />
</TextBlock.ToolTip>
</TextBlock>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
However, what this does is very briefly show the tooltip and then the content in the cell is removed, so nothing shows up at all. Also, setting the tooltip from outside the Template setter is an option, but I'm not sure what the corrent binding is to do that.
My example here is for a simple label but this can be applied to other controls.
<Label Name="lblFormName" Content="Form Elements:" FontWeight="Bold" HorizontalAlignment="Left" Width="295" >
<Label.ToolTip>
<Binding ElementName="lblFormName" Path="Content"/>
</Label.ToolTip>
</Label>
Check out this link: http://msdn.microsoft.com/en-us/library/ms742167.aspx
or this link for a bunch of binding "how-to"s from MS http://msdn.microsoft.com/en-us/library/ms752039.aspx
Have you tried using RelativeSource? I heard of some issues about TemplateBinding vs. RelativeSource (WPF TemplateBinding vs RelativeSource TemplatedParent).
<ContentPresenter Content="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type YourAncestorType}, AncestorLevel=1},Path=Content}" />
Where "YourAncestorType" is the type of the parent you want to find.
Or you could also try the same approach with
<ContentPresenter Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}" />
See also: http://www.wpfwiki.com/Default.aspx?Page=WPF%20Q5.3&AspxAutoDetectCookieSupport=1
Try removing the ToolTip from the ControlTemplate and defining a separate Setter in the Style for the Tooltip.
Here is the XAML using your sample:
<Style x:Key="CellStyle" TargetType="{x:Type WpfToolkit:DataGridCell}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="WpfToolkit:DataGridCell">
<Grid>
<TextBlock Margin="2" VerticalAlignment="Center"
HorizontalAlignment="Left" TextWrapping="Wrap" >
<ContentPresenter Content="{TemplateBinding Property=ContentControl.Content}" />
<!--<TextBlock.ToolTip>
<ContentPresenter Content="{TemplateBinding Property=ContentControl.Content}" />
</TextBlock.ToolTip>-->
</TextBlock>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.Text}"/>
</Style>

Resources