Window.Margin & Window.Padding don't work - wpf

I am setting peroperty Margin and Padding of a window and it doesn't take effect:
Here is an example:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
SizeToContent="WidthAndHeight"
ResizeMode="NoResize"
Padding="22"
Margin="22">
<Grid>
<Label
FontWeight="Bold"
FontSize="36"
BorderThickness="1"
BorderBrush="Red"
Content="Hello world!"/>
</Grid>
</Window>
Result:
The desired result is that the red frame of the lable should be away 44px from the window's frame (margin+padding).
Yes, I know I can set the margin of the label, but that's not what I want.
I have a whole project that all its windows are set to a style, I want to set this properties (or other) in the general window style.
I guess if I won't find any solution I will create a named style for greed where I will set the margin/padding, then I will go Window by window and set the Grid's style, but that's the last option I wanna do.
Thanks in advance.

It's not surprising that Margin doesn't work, because Margin is the amount of space to be placed around the control. For a Window, this would mean making the frame smaller (and offset), not the client area, and that would be a bit strange (and might not play nicely with the Win32 hosting environment, not sure). It is a bit surprising that Padding doesn't work, and I'm not sure why that would be.
However, there is a workaround which you can encapsulate in a style: replace the default Window ControlTemplate with your own template that does respect the Padding:
<ControlTemplate TargetType="Window">
<Border Background="White" Padding="{TemplateBinding Padding}">
<ContentPresenter />
</Border>
</ControlTemplate>
(You would probably want the Border Background to be the dynamic window background brush for production code, but you get the idea.)
Obviously you can put this template in a style Template setter so as to avoid having to repeat it on each Window.
Here is the full template (generated with Microsoft Expression):
<Style x:Key="WindowStyle" TargetType="{x:Type Window}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Margin="{TemplateBinding Margin}"
Padding="{TemplateBinding Padding}">
<AdornerDecorator>
<ContentPresenter/>
</AdornerDecorator>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="ResizeMode" Value="CanResizeWithGrip">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<AdornerDecorator>
<ContentPresenter/>
</AdornerDecorator>
<ResizeGrip
x:Name="WindowResizeGrip"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
IsTabStop="false"
Visibility="Collapsed"
/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition
Property="ResizeMode"
Value="CanResizeWithGrip"
/>
<Condition
Property="WindowState"
Value="Normal"
/>
</MultiTrigger.Conditions>
<Setter
Property="Visibility"
TargetName="WindowResizeGrip"
Value="Visible"/>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>

Here's a simple alternative: just set a background colour on your Window and the Margin on the Grid within your Window:

Related

WPF Button to CheckBoxTemplate

I am trying to give checkBox controltemplate to Button seeing an example in WPF Unleashed Text Book.
<ControlTemplate x:Key="buttoncheckBox" TargetType="{x:Type Button}">
<Grid>
<Rectangle Width="20" Height="20" x:Name="outerCircle" Stroke="Black" StrokeThickness="0.5">
</Rectangle>
<Rectangle Width="10" Height="10" x:Name="InnerCircle">
</Rectangle>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="Button.IsMouseOver" Value="True">
<Setter TargetName="outerCircle" Property="Stroke" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"></Setter>
</Trigger>
<Trigger Property="Button.IsPressed" Value="True">
<Setter TargetName="InnerCircle" Property="Fill" Value="Orange"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Button Template="{StaticResource buttoncheckBox}" Margin="10" Padding="10"/>
Here When I hover mouse or press it is not triggering events everywhere but only when I click on the border it is triggering.
When I use textbook example it is working anywhere what is difference I don't understand.
The problem is that the Grid you are using has no Background.
This is to fix your issue:
<ControlTemplate x:Key="buttoncheckBox" TargetType="{x:Type Button}">
<Grid Background="Transparent" Width="20" Height="20">
.....
You will have to check to see how you can make this code work with different resolutions. Now it seems to be only for 20x20.
In general, when you don't set a Background for a control or a panel such as the Grid, the area is considered to belong to the parent window and that's why no mouse events get raised.
If you don't want any actual background you should still set the Background property of the Grid to Transparent for the mouse movements and the clicks to be registered.
You don't need to specify a fixed size for the Grid though. Just setting the Background should be enough:
<ControlTemplate x:Key="buttoncheckBox" TargetType="{x:Type Button}">
<Grid Background="Transparent">
...
The only element that is currently available for hit test is the Rectangle.Stroke (the small border or line) When you interact with that thin line you will recognize that it will behave as you would expect. To make the whole Rectangle hit test visible you have to set the Rectangle.Fill property of both Rectangles:
<Rectangle Fill="Transparent" />
To allow the Button to resize properly use a Border. To enable the Button to display content like an icon or label text you need to add a ContentPresenter:
<ControlTemplate x:Key="buttoncheckBox" TargetType="{x:Type Button}">
<Border x:Name="outerCircle"
Margin="{TemplateBinding Margin}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<Grid>
<Rectangle x:Name="InnerCircle" />
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Button.IsMouseOver"
Value="True">
<Setter TargetName="outerCircle"
Property="BorderBrush"
Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}">
</Setter>
</Trigger>
<Trigger Property="Button.IsPressed"
Value="True">
<Setter TargetName="InnerCircle"
Property="Fill"
Value="Orange">
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
and use it like this:
<Button Background="Transparent"
Width="80" Height="80"
Padding="5"
Template="{StaticResource buttoncheckBox}"
BorderBrush="Black"
BorderThickness="0.5"
Content="Label Text" />
Modify Button.Padding to resize the inner Rectangle.

Xaml switch between TextBlock and TextBox

I've noticed that TextBoxes are very slow and create performance issues when the Text is changed dynamically by code (I need to change the Text continuosly to 10-15 TextBoxes at the same time), so, as a workaround, I've created a custom control with a TextBlock and a TextBox:
The TextBlock is used in almost all time.
The TextBox is used only when I need to edit the Text inside the control with keyboard.
My solution is to change the template and use the TextBox when the control is focused:
(Value is a string Dependency Property)
<Style TargetType="{x:Type local:CustomControl1}">
<Setter Property="Value" Value="Val"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustomControl1}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{TemplateBinding Value}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustomControl1}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<TextBox HorizontalContentAlignment="Center" VerticalContentAlignment="Center"
Text="{Binding Path=Value, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
But when I click on the control nothing happens.
I think that the problem is that the "focus state" is passed to the internal TextBox, and the control loses the "focus state".
There is a better way to create a custom "TextBox" control like this, or a way to resolve this problem?
You don't need a custom control for this, that's just adding unnecessary overhead. What you're trying to create is still a TextBox, with all the usual behavior of a TextBox (focus etc). All you need to do is change the template to a TextBlock when it's not in focus:
<Window.Resources>
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="IsFocused" Value="False">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<TextBlock Text="{TemplateBinding Text}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<TextBox Text="Hello World" />
<TextBox Text="Goodbye World" />
</StackPanel>

Remove ToggleButton annoying background Mouse over style

I have simple ToggleButton and when IsChecked i want to change only the text.
I want all other properties like border and background will be Transparent but it seems that i still have this background style:
<ToggleButton x:Name="changeButBorderedBlinky" Content="EDIT" Width="40" Height="40" Background="Transparent">
<ToggleButton.Style>
<Style TargetType="{x:Type ToggleButton}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Content" Value="Done"/>
<Setter Property="FontWeight" Value="Bold"/>
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
One thing that is often annoying is some visual aspects of the default WPF controls are coded in a way so as they are not configurable. The MouseOver Background is an example (scrollbar sizes is another... grrr!!!). You can solve this though by defining your own Template for the ToggleButton and eliminate that MouseOver trigger. Here is a simple example:
<ToggleButton x:Name="changeButBorderedBlinky" Width="40" Height="40" Background="Transparent">
<ToggleButton.Style>
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="Content" Value="EDIT"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border x:Name="border"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
SnapsToDevicePixels="True">
<ContentPresenter x:Name="contentPresenter"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
ContentStringFormat="{TemplateBinding ContentStringFormat}"
Focusable="False"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Content" Value="Done"/>
<Setter Property="FontWeight" Value="Bold"/>
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
Also, in order to change a property in a trigger it has to be set in a style, not directly. That is why your Content doesn't change in your MouseOver Trigger. If you remove the property setting for it and
add it into the Style with a Setter, it will allow the trigger to change it.
One downside to all this is it overrides all the default template triggers so you won't see when the ToggleButton is checked anymore unless you add a trigger for "IsChecked" too. (and if you need to alter the Background in the trigger, move the Background Property to a Setter like I did for Content)
Hope that helps...
Sorry to revive an old thread, but (for someone struggling) the following worked for me. This can be in App.xaml file under Application.Resources tag or directly in the Window.Resources. I originally needed it for a UWP application, then had to adapt for WPF for a different project:
<Style TargetType="ToggleButton" x:Key="TransparentToggleButtonStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid x:Name="RootGrid" Background="Transparent">
<ContentPresenter x:Name="ContentPresenter" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Then just style your ToggleButton:
<ToggleButton Style="{StaticResource TransparentToggleButtonStyle}">
(whatever content you want to present)
</ToggleButton>
Hope this helps someone,

How to change the background colour of column header of a WPF datagrid without affecting other properties

The style used for column header :-
<Style x:Key="DataGridColumnHeaderStyle" TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
<Grid VerticalAlignment="Bottom" HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<theme:DataGridHeaderBorder Grid.Column="0" Grid.Row="0" SortDirection="{TemplateBinding SortDirection}"
IsHovered="{TemplateBinding IsMouseOver}"
IsPressed="{TemplateBinding IsPressed}"
IsClickable="{TemplateBinding CanUserSort}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding ="{TemplateBinding Padding}"
SeparatorVisibility="{TemplateBinding SeparatorVisibility}"
ContextMenu="{DynamicResource DataGridColumnHeaderContextMenu}"
SeparatorBrush="{TemplateBinding SeparatorBrush}">
<TextBlock Grid.Column="0" Grid.Row="0" Text="{TemplateBinding Content}" FontWeight="Bold"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Padding ="{TemplateBinding Padding}"
TextWrapping="NoWrap"></TextBlock>
</theme:DataGridHeaderBorder>
<Thumb Grid.Column="0" Grid.Row="0" Name="PART_LeftHeaderGripper" HorizontalAlignment="Left">
<Thumb.Style>
<Style TargetType="Thumb">
<Style.Resources>
<ResourceDictionary />
</Style.Resources>
<Setter Property="FrameworkElement.Width">
<Setter.Value>
<thumbConversion:Double>8</thumbConversion:Double>
</Setter.Value>
</Setter>
<Setter Property="Panel.Background">
<Setter.Value>
<SolidColorBrush>#00FFFFFF</SolidColorBrush>
</Setter.Value>
</Setter>
<Setter Property="FrameworkElement.Cursor">
<Setter.Value>
<Cursor>SizeWE</Cursor>
</Setter.Value>
</Setter>
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="Thumb">
<Border Padding="{TemplateBinding Control.Padding}" Background="{TemplateBinding Panel.Background}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Thumb.Style>
</Thumb>
<Thumb Grid.Column="0" Grid.Row="0" Name="PART_RightHeaderGripper" HorizontalAlignment="Right">
<Thumb.Style>
<Style TargetType="Thumb">
<Style.Resources>
<ResourceDictionary />
</Style.Resources>
<Setter Property="FrameworkElement.Width">
<Setter.Value>
<thumbConversion:Double>8</thumbConversion:Double>
</Setter.Value>
</Setter>
<Setter Property="Panel.Background">
<Setter.Value>
<SolidColorBrush>#00FFFFFF</SolidColorBrush>
</Setter.Value>
</Setter>
<Setter Property="FrameworkElement.Cursor">
<Setter.Value>
<Cursor>SizeWE</Cursor>
</Setter.Value>
</Setter>
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="Thumb">
<Border Padding="{TemplateBinding Control.Padding}" Background="{TemplateBinding Panel.Background}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Thumb.Style>
</Thumb>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Before changing the Background color, the Column header looks like this.
I changed the Background color by adding
<Style x:Key="DataGridColumnHeaderStyle" TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Background" Value="White" />
<Setter Property="Template">
...........
It overrides everything I have specified in the template property. The sort symbols are not shown.
Then I tried adding the background color in the TextBlock part of the template. I changed the horizontal and vertical alignments to "Stretch" and provided the background color. The sort symbols are chopped and it looks ugly when I select the header.
I just want to change the background color. How do I do it?
You cannot change the Background colour of the DataGridHeaderBorder without losing the sort arrows.
If you set the Background property you will have to create the sort arrows yourself in your custom template.
The default background that you see is actually drawn in the OnRender method of the Microsoft.Windows.Themes.DataGridHeaderBorder class. It is not defined in some XAML template.
First in your DataGridView you need to set EnableHeadersVisualStyles to false. After you've done that you can set the individual header style on each column.
DataGridViewColumn dataGridViewColumn = dataGridView1.Columns[0];
dataGridViewColumn.HeaderCell.Style.BackColor = Color.Magenta;
dataGridViewColumn.HeaderCell.Style.ForeColor = Color.Yellow;

Custom Simple Scrollbar linked to Listview

The default scrollbar for a listview appears at the right. I designed a new style and would like it to appear separate from the listview control. What you see in the image is how I have it set up now using blend.
So how do I link the custom scroll bar to the listview? I'm using Blend 4.
Listview Image located here:
http://i141.photobucket.com/albums/r69/thebirdbath/scroll.jpg
I'm not sure if you want to add your Style to the ScrollViewer inside the Template of the ListView or if you want to disable that ScrollViewer and place the ListView in a separate ScrollViewer.
To apply the Style to the ScrollViewer in the Template and place the ScrollBar to the left you can modify the default Template when using GridView. It will require a reference to PresentationFramework.Aero
Set FlowDirection="RightToLeft" on the ScrollViewer to place it on the left side
Set FlowDirection="LeftToRight" on the ItemsPresenter and GridViewHeaderRowPresenter since they will inherit RightToLeft otherwise
To get the transparent space between the ScrollViewer and the content, set Background="Transparent" for the ListView and set the desired Background on the ItemsPanel instead
Control the transparent space with Padding, e.g. Padding="0,0,10,0"
Looks like this
<ListView xmlns:MS_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
Padding="0,0,10,0"
Background="Transparent"
BorderThickness="0"
ScrollViewer.VerticalScrollBarVisibility="Visible">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Background="White"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.Template>
<ControlTemplate TargetType="{x:Type ListView}">
<MS_Themes:ListBoxChrome x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" SnapsToDevicePixels="true">
<ScrollViewer Padding="{TemplateBinding Padding}"
Style="{YourStyle...}"
FlowDirection="RightToLeft">
<ScrollViewer.Resources>
<Style TargetType="GridViewHeaderRowPresenter">
<Setter Property="FlowDirection" Value="LeftToRight"/>
</Style>
</ScrollViewer.Resources>
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
FlowDirection="LeftToRight"/>
</ScrollViewer>
</MS_Themes:ListBoxChrome>
<ControlTemplate.Triggers>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ListView.Template>
<!--...-->
</ListView>
Ok, pretty close. Its working but I've lost my column headers. Also I can't get the transparency in between the bar and the listview. Its like the bar is still attached and I want them to appear like they are separate. (See the link to my original image)
This has been very helpful. Almost there!
My code is below.
<ListView
AlternationCount="2"
Padding="0,0,10,0"
Shared:GridViewSort.AutoSort="True"
Shared:GridViewSort.ShowSortGlyph="True"
ItemsSource="{Binding Contents}"
SelectionMode="Extended"
Background="Transparent"
Foreground="White"
SelectionChanged="ListBoxSelectionChanged"
BorderThickness="0"
ItemContainerStyle="{DynamicResource ListViewItemStyle}"
Style="{DynamicResource ListViewStyle1}" Margin="0" VerticalAlignment="Top">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Background="Transparent"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.Template>
<ControlTemplate TargetType="{x:Type ListView}">
<MS_Themes:ListBoxChrome x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" SnapsToDevicePixels="true">
<ScrollViewer Padding="{TemplateBinding Padding}"
Style="{DynamicResource ScrollViewerKey}"
FlowDirection="RightToLeft">
<ScrollViewer.Resources>
<Style TargetType="GridViewHeaderRowPresenter">
<Setter Property="FlowDirection" Value="LeftToRight"/>
</Style>
</ScrollViewer.Resources>
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
FlowDirection="LeftToRight"/>
</ScrollViewer>
</MS_Themes:ListBoxChrome>
<ControlTemplate.Triggers>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ListView.Template>

Resources