DataGrid header alignment - wpf

I populate a DataGrid control using DataSet in WPF(c#). I need a way align text of header to center.
Note: During running of my program, It is possible to DataGrid.ItemsSource updated.
It is not same as my previous questions...

<DataGrid ItemsSource="{Binding Items}"
AutoGenerateColumns="True">
<DataGrid.ColumnHeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Style.Setters>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style.Setters>
</Style>
</DataGrid.ColumnHeaderStyle>
</DataGrid>

You just have to style the HorizontalContentAlignment property of the DataGridColumnHeader type. So add to the resources:
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
Addendum In general, you can see the control templates at this page on MSDN, which allows you to deduce how to apply the styles you need. In this case, the template for the control DataGridColumnHeader looks like this:
<Grid>
<Border x:Name="columnHeaderBorder" BorderThickness="1" Padding="3,0,3,0">
<!-- (ellided brushes for brevity) -->
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
<Thumb x:Name="PART_LeftHeaderGripper"
HorizontalAlignment="Left"
Style="{StaticResource ColumnHeaderGripperStyle}" />
<Thumb x:Name="PART_RightHeaderGripper"
HorizontalAlignment="Right"
Style="{StaticResource ColumnHeaderGripperStyle}" />
</Grid>
The ContentPresenter is where the header text is displayed -- you can see that has its HorizontalAlignment set to the control's HorizontalContentAlignment (TemplateBinding). Hence all that's needed is to set that style property on the control type DataGridColumnHeader.

Related

WPF: Problem applying style to custom TabItem Header through ControlTemplate and ContentPresenter.Resources

I am trying to write my own control template for a TabItem Header, and have got the basic layout to work but now I wish to apply styling to the content of the Header, for example to manipulate the size and font of a textblock.
In order to test this, I have put an ellipse in the tabitem header and am attempting to fill that ellipse with the Gold brush through styling. However, it is not working. The ellipse is present, and the control template is being applied, but the fill of the ellipse is not Gold. The style within the ContentPresenter.Resources is being ignored (and Resharper has even greyed it out to prove that). Any ideas what I'm doing wrong? Thanks.
Here is the code:
<TabItem>
<TabItem.Template>
<ControlTemplate x:Name="theTabItemControlTemplate" TargetType="{x:Type TabItem}">
<Border BorderBrush="DarkBlue" BorderThickness="10">
<Grid>
<ContentPresenter ContentSource="Header" RecognizesAccessKey="True">
<ContentPresenter.Resources>
<Style TargetType="{x:Type Ellipse}">
<Setter Property="Ellipse.Fill" Value="Gold"/>
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
</Grid>
</Border>
</ControlTemplate>
</TabItem.Template>
<TabItem.Header>
<Ellipse Stroke="Black" StrokeThickness="2" Width="100" Height="30" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</TabItem.Header>
</TabItem>
Move your style one level upper.ie,move it to ControlTemplate.Resources and it will work fine.I am quite not sure why the code in the question does not work.It may be because the controls in the contentpresenter is already built by the time the style is encountered.
<ControlTemplate x:Name="theTabItemControlTemplate" TargetType="{x:Type TabItem}">
<ControlTemplate.Resources>
<Style TargetType="{x:Type Ellipse}">
<Setter Property="Fill" Value="Red"/>
</Style>
</ControlTemplate.Resources>
<Border BorderBrush="DarkBlue" BorderThickness="10">
<Grid>
<ContentPresenter ContentSource="Header" RecognizesAccessKey="True">
</ContentPresenter>
</Grid>
</Border>
</ControlTemplate>

How do I stretch the contents of a HeaderedContentControl?

I have a HeaderedContentControl that contains a TreeView.
<HeaderedContentControl Header="Steps" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TreeView Name="WizardSteps" ItemsSource="{Binding WizardSteps}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<!-- Hierarchical data templates here -->
</TreeView>
</HeaderedContentControl>
Although the HeaderedContentControl stretches to fill the area inside its parent grid, my TreeView control only occupies a small portion of the space available.
How do I get my TreeView to expand to fill the content area of my HeaderedContentControl?
The default control template for HeaderedContentControl is something like this:
<ControlTemplate TargetType="{x:Type HeaderedContentControl}">
<StackPanel>
<ContentPresenter ContentSource="Header" />
<ContentPresenter />
</StackPanel>
</ControlTemplate>
The StackPanel lets each child have its own desired height, so the TreeView won't stretch. You could replace it with a template that uses a DockPanel:
<HeaderedContentControl Header="Steps" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" VerticalContentAlignment="Stretch" >
<HeaderedContentControl.Template>
<ControlTemplate TargetType="HeaderedContentControl">
<DockPanel>
<ContentPresenter DockPanel.Dock="Top" ContentSource="Header" />
<ContentPresenter />
</DockPanel>
</ControlTemplate>
</HeaderedContentControl.Template>
If you want to make it more reusable, set the template in a Style and use VerticalContentAlignment:
<Style TargetType="HeaderedContentControl">
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="HeaderedContentControl">
<DockPanel>
<ContentPresenter DockPanel.Dock="Top" ContentSource="Header" />
<ContentPresenter VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
That way, all your HeaderedContentControls will have their content fill by default, and you can override that by setting VerticalContentAlignment on an individual control.
Alternately, you could use a DockPanel directly instead of a HeaderedContentControl.

WPF Expander Button Styled so it is inside Expander Header

I am using the Expander control and have styled the header as shown in the picture below:
http://www.hughgrice.com/Expander.jpg
The problem I have is that I want the expander button to be contained within the header so that the line for the end of the header template aligns with the Expander content i.e. I ultimatly want to end up with something similar to the image below:
http://www.hughgrice.com/Expander.gif
Thanks in advance.
I see that you want to actually move the expander button into your HeaderTemplate, not just restyle it. This is easily done with FindAncestor:
First add a ToggleButton and bind its IsChecked property using FindAncestor, along these lines:
<DataTemplate x:Key="MyHeaderTemplate">
<Border ...>
<DockPanel>
<!-- Expander button -->
<ToggleButton
IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor,Header,1}}"
Content=... />
<!-- Other content here -->
...
</DockPanel>
</Border>
</DataTemplate>
This adds an expand button inside the header template but does not hide the original button provided by the Expander. To do this I recommend you replace the Expander's ControlTemplate.
Here is a complete copy of Expander's ControlTemplate with the ToggleButton replaced with a simple ContentPresenter:
<ControlTemplate x:Key="ExpanderWithoutButton" TargetType="{x:Type Expander}">
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
CornerRadius="3"
SnapsToDevicePixels="true">
<DockPanel>
<ContentPresenter
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
ContentTemplateSelector="{TemplateBinding HeaderTemplateSelector}"
DockPanel.Dock="Top"
Margin="1"
Focusable="false" />
<ContentPresenter
x:Name="ExpandSite"
Visibility="Collapsed"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="{TemplateBinding Padding}"
Focusable="false" />
</DockPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="true">
<Setter Property="Visibility" Value="Visible" TargetName="ExpandSite"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
It might be used as follows:
<Expander Template="{StaticResource ExpanderWithoutButton}">
<Expander.HeaderTemplate>
<DataTemplate ...>
<Border ...>
<DockPanel>
<ToggleButton ...
IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor,Header,1}}" />
... other header template content here ...
A simpler alternative would be to just set a negative margin in yourHeaderTemplate to cover the expander button. Instead of the ControlTemplate shown above, your DataTemplat would just contain something like this:
<DataTemplate ...>
<Border Margin="-20 0 0 0" ... />
Adjust the negative margin to get the look you want. This solution is simpler but inferior in that if you switch to a different system theme the required margin may change and your expander may no longer look good.
You will need to edit the Expander's Template, not the HeaderTemplate. The HeaderTemplate doesn't contain the expand button, just the content inside of it.
The default control template looks something like this:
<ControlTemplate TargetType="{x:Type Expander}">
<Border>
<DockPanel>
<ToggleButton x:Name="HeaderSite"
ContentTemplate="{TemplateBinding HeaderTemplate}"
Content="{TemplateBinding Header}"
DockPanel.Dock="Top"
IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" />
<ContentPresenter x:Name="ExpandSite" />
</DockPanel>
</Border>
</ControlTemplate>
I took out most of the attributes but left in the important stuff. Basically, you will want to add your customizations around the ToggleButton. That is what contains the expand button and the header content.
If you have Expression Blend, it makes this process much easier because you can simply edit a copy of the original template. Visual Studio doesn't really have this ability yet.

Does anyone have a simple example of a UserControl with a single ContentPresenter?

So far, I have this:
<UserControl
x:Class="MyConcept.ExpanderPanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Border
Style="{StaticResource Border_PanelStyle}"
CornerRadius="3" />
<ContentPresenter />
</Grid>
</UserControl>
Sample usage of this UserControl:
<nc:ExpanderPanel
Grid.Row="0">
<Expander
IsExpanded="True"
Header="NMT Users">
<StackPanel>
...
</StackPanel>
</Expander>
</nc:ExpanderPanel>
Discussion
If I run this, I see nothing. No content is presented, not even the border that is built into the UserControl.
I thought maybe I needed to make the ContentPresenter a dependency property, but I couldn't figure out how I would link the property to the ContentPresenter in the UserControl's XAML.
Can someone provide a simple example that shows how to build a UserControl (or some kind of custom control) with a single ContentPresenter?
ContentPresenters are main used in ControlTemplates and bound with a TemplateBinding to the ContentControl.Content.
from this site... a control template for a button that uses a ContentPresenter
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="White" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Rectangle Fill="{TemplateBinding Property=Background}" />
<ContentPresenter
Content="{TemplateBinding Property=ContentControl.Content}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

How can I change the font size of a label in my ControlTemplate

In my WPF ListBox, I have a style with a ControlTemplate for a ListBoxItem. Inside that ControlTemplate I have a label defined. Based on some details, I need to change the font size of the label. So from my code-behind, I need to determine what the font should be and then I need to set it.
Here is my style with the ControlTemplate (I've stripped out some irrelevant controls)
<Style x:Key="RecordTabList" TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="{DynamicResource RecordIndexTabBackcolor}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Label
x:Name="myLabel" Grid.Column="0" Grid.ColumnSpan="1" Grid.Row="0" Grid.RowSpan="1" Margin="3,-2,0,-2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Foreground="{DynamicResource RecordIndexTabForeground}"
FontSize="10" Height="Auto" BorderThickness="3,0,0,0"
Content="{Binding Path=Name}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
How can I do this?
If I understand you correctly, you can probably do something similar to the following, and simply change the FontSize property on the ListBoxItem itself; it will be reflected automatically on your Label. Copy this into VS and see it in action!
<Window.Resources>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Label Content="{TemplateBinding Content}" FontSize="{TemplateBinding FontSize}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<ListBox Margin="12">
<ListBoxItem Content="Test 1" FontSize="14"/>
<ListBoxItem Content="Test 2" FontSize="18"/>
<ListBoxItem Content="Test 3" FontSize="22"/>
</ListBox>
</Grid>
You might be able to use a ValueConverter on the FontSize property.. but I'm not 100% sure if they work inside a ControlTemplate.. I seem to remember Silverlight having issues with it, but I can't remember if it worked in WPF.
If you want to set the FontSize in the code behind, you should remove FontSize from the ControlTemplate, then set it for the ListBoxItem in the code-behind. If you want to set the same size for all the ListBoxItems just set the FontSize of the ListBox in the code-behind.

Resources