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.
Related
I have created a Groupbox resource directory, and created a style that affects the groupbox.
Here is my Resource Directory code:
<Style x:Key="grpNumbers" TargetType="GroupBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GroupBox">
<Border
BorderThickness="1"
BorderBrush="#25A0DA" CornerRadius="10">
<Label HorizontalAlignment="Left" Content="Carrier" Foreground="White" Background="#151515" Height="38"
Margin="30,-195,0,0"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The issue is that I want the group box style to not be coupled with the Content in the Label.
Currently it is getting instantiated in the mainwindow like this:
<GroupBox Style="{StaticResource ResourceKey=grpNumbers}" Grid.Column="1" BorderBrush="#272727" Grid.Row="1" Height="200" Margin="20" HorizontalAlignment="Stretch" Header="Carrier information" Foreground="White" FontSize="20" BorderThickness="0.2">
</GroupBox>
But obviously the above groupboxes' Header tag isn't overriding the header of my custom groupbox but I need it too, can this be done?
Label inside ContentTemplate can use TemplateBinding to bind Header:
<Label Content="{TemplateBinding Header}"/>
You should modify your Style too look like this:
<Style x:Key="grpNumbers" TargetType="{x:Type GroupBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupBox}">
<Grid>
<Border BorderThickness="1"
BorderBrush="#25A0DA"
CornerRadius="10">
<Label HorizontalAlignment="Left"
Content="{TemplateBinding Header}"
Foreground="White"
Background="#151515"
Height="38"
Margin="30,-195,0,0"/>
</Border>
<!-- Responsible for displaying what you put inside of your GroupBox -->
<ContentPresenter Margin="5,25,5,5" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
which can then be used like this:
<GroupBox Style="{StaticResource grpNumbers}"
Grid.Column="1"
BorderBrush="#272727"
Grid.Row="1"
Height="200"
Margin="20"
HorizontalAlignment="Stretch"
Header="Carrier information"
Foreground="White"
FontSize="20"
BorderThickness="0.2">
<TextBox /> <!-- or whatever you want inside your GroupBox -->
</GroupBox>
Currently I am working on wpf popup which contains a label, which constitute of textblocks inside the control template. Here my issue is that popup has a bottom border shadow. Already a border is there for the popup along with that this shadow effect increases the bottom border thickness, which looks like this (check the link below to see the screenshot for popup).
Wpf code is like this
Label Control template style
<Style x:Key="popuplabelstyle" TargetType="{x:Type Label}">
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Label}">
<Border BorderBrush="Red" x:Name="labelBorder" BorderThickness="1" Padding="12" Background="White" Height="auto" MinHeight="260" Width="220">
<StackPanel>
<TextBlock Text="ABCD" Margin="0,0,0,4" />
<TextBlock Text="abcd" Margin="0,4,0,0" />
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
xaml code for popup
<Popup x:Name="Mypopup" Panel.ZIndex="2" Placement="MousePoint" HorizontalOffset="10" VerticalOffset="10" IsOpen="{Binding ">
<Label Style="{StaticResource popuplabelstyle}"/>
</Popup>
I don't know why it's happening like this. Can anyone help me to solve this?
See the screenshot of the popup in below link
Try to set the SnapsToDevicePixels and/or UseLayoutRounding property of the Border to True to enable pixel snap rendering:
<ControlTemplate TargetType="{x:Type Label}">
<Border BorderBrush="Red" x:Name="labelBorder"
BorderThickness="1" Padding="12" Background="White" Height="auto" MinHeight="260" Width="220"
SnapsToDevicePixels="True" UseLayoutRounding="True">
<StackPanel>
<TextBlock Text="ABCD" Margin="0,0,0,4" />
<TextBlock Text="abcd" Margin="0,4,0,0" />
</StackPanel>
</Border>
</ControlTemplate>
This should make the Border look sharper.
When should I use SnapsToDevicePixels in WPF 4.0?
If I replace a ScrollViewer control template so that it contains another scroll viewer then some of the time they scroll together.
For example the GridView class has a variation on the following template which ensures that the column headers always line up with the contents of the list view, even when the user scrolls to the right (in this sample "Columns" is a GridViewColumnCollection filled with columns)
<ScrollViewer HorizontalScrollBarVisibility="Visible">
<ScrollViewer.Style>
<Style TargetType="{x:Type ScrollViewer}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<DockPanel>
<ScrollViewer DockPanel.Dock="Top">
<GridViewHeaderRowPresenter Columns="{StaticResource Columns}" />
</ScrollViewer>
<ScrollBar DockPanel.Dock="Bottom" Name="PART_HorizontalScrollBar" Orientation="Horizontal"
Minimum="0.0" Maximum="{TemplateBinding ScrollableWidth}" ViewportSize="{TemplateBinding ViewportWidth}"
Value="{Binding Path=HorizontalOffset,RelativeSource={RelativeSource TemplatedParent},Mode=OneWay}" />
<ScrollContentPresenter Name="PART_ScrollContentPresenter" Content="{TemplateBinding Content}" />
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ScrollViewer.Style>
<GridViewHeaderRowPresenter Columns="{StaticResource Columns}" />
</ScrollViewer>
How does this work?
(I'm asking because I need to modify the GridView templates and I've managed to break this functionality - I'm trying to work out how to fix it but finding it difficult because I don't understand why it works in the first place!)
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>
What I want: To get the darn horizontal scrollbar to appear. I will be editing it a bit just so i fits the rest of the app's style scheme, but not too much.
What I have
Here is the code for the listbox as of now. Everything runs perfectly except the scrollbars dont appear. You might say... "well you dont have a scrollviewer anywhere", but I have tried inserting a scrollviewer in numerous places and still no luck.
The Listbox Code:
<ListBox ItemsSource="{Binding Items}" ItemTemplate="{StaticResource itemsdatatemplate}" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="{x:Null}" ItemsPanel="{StaticResource HorizontalListBoxTemplate}" ItemContainerStyle="{StaticResource TransparentListBox}" VerticalAlignment="Center" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" />
The 'TransparentListBox' (to shut-up the selected background color):
<Style x:Key="TransparentListBox" TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid>
<Border x:Name="HoverBorderBackgroundBrush" BorderThickness="1" Margin="0,0,25,0" Background="Transparent"/>
<Border x:Name="SelectedBorderBackgroundBrush" BorderThickness="1" Margin="0,0,25,0" Background="Transparent"/>
<ContentPresenter></ContentPresenter>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Horizontal List Box (to make the listbox Horizontal, rather than standard vertical)
<ItemsPanelTemplate x:Key="HorizontalListBoxTemplate">
<StackPanel Orientation="Horizontal">
</StackPanel>
</ItemsPanelTemplate>
The Datatemplate (to actually show the Items)
<DataTemplate x:Key="itemsdatatemplate">
<local:ListItemControl HorizontalAlignment="Left" VerticalAlignment="Top" DataContext="{Binding}"/>
</DataTemplate>
I have a feeling its going to be a simple addition, but Thanks in advance.
Update
It looks like the scrollbars now do appear with this:
<Style x:Key="ScrollingListBox" TargetType="ListBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<ScrollViewer HorizontalScrollBarVisibility="Visible">
<ItemsPresenter></ItemsPresenter>
</ScrollViewer>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
But they do not function accordingly. They feel... broken. However, if one was to define a static width (say 300) of the grid, then the ScrollViewer acts perfectly. Right now I have a completely fluid layout (meaning things stretch to fill), is this not acceptable for scrollviewers?
When you create your own template, you have to define the ScrollViewer in there and use an ItemPresenter instead of a ContentPresenter.
<Style x:Key="TransparentListBox" TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid>
<Border x:Name="HoverBorderBackgroundBrush" BorderThickness="1" Margin="0,0,25,0" Background="Transparent"/>
<Border x:Name="SelectedBorderBackgroundBrush" BorderThickness="1" Margin="0,0,25,0" Background="Transparent"/>
<ScrollViewer x:Name="ScrollViewer" HorizontalScrollBarVisibility="Visible">
<ItemsPresenter />
</ScrollViewer>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>