UserControl content is empty when trying to use ContentPresenter inside DataTemplate - wpf

I have a main abstract code-only class BaseImpostorButton, inheriting UserControl. I have a child class ClickableImageButton with xaml and code-behind.
I'm using the following style with ControlTemplate :
<Style TargetType="{x:Type local:ClickableImageButton}">
<Setter Property="ToolTipService.InitialShowDelay" Value="0"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ClickableImageButton}">
<StackPanel Margin="{TemplateBinding Margin}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}">
<ContentPresenter
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
When using in a ListView as raw ListViewItem, my ClickableImageButton shows correctly.
BUT: when using it in a listview with ItemTemplate DataTemplate, the ClickableImageButton is no longer shown... as if the Content was empty when inside a DataTemplate.
The solution i found was to write a DependencyProperty ButtonContent on BaseImpostorButton and set it explicitly in xaml.
But can someone explain this issue ?
EDIT: Here are the 2 different xaml
The one that is correctly showing the underlying image (ClickableImage is an Image)
<ListView Grid.Row="1" Name="ListViewSections" ItemsSource="{Binding Path=Sections}" Background="{x:Null}" SizeChanged="ListViewSections_SizeChanged">
<ListViewItem>
<Grid MaxWidth="600">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition MaxWidth="150"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.ColumnSpan="2" Text="{Binding Path=Titre}" Margin="5,0,5,0" FontSize="18" FontWeight="Bold" Foreground="White" TextWrapping="Wrap" FontFamily="Arial" HorizontalAlignment="Left" />
<local:ClickableImageButton Grid.Row="1" Tag="{Binding Path=Id}" Grid.Column="0" ImpostorClick="Image_Click" Margin="10">
<local:ClickableImageButton.Content>
<local:ClickableImage Source="Content/tada.png" />
</local:ClickableImageButton.Content>
</local:ClickableImageButton>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=Texte}" Margin="10,0,10,0" FontSize="16" Foreground="White" TextWrapping="Wrap" FontFamily="Arial" VerticalAlignment="Center" HorizontalAlignment="Left" />
</Grid>
</ListViewItem>
</ListView>
And the one that's not working
<ListView Grid.Row="1" Name="ListViewSections" ItemsSource="{Binding Path=Sections}" Background="{x:Null}" SizeChanged="ListViewSections_SizeChanged">
<ListView.ItemTemplate>
<DataTemplate>
<Grid MaxWidth="600">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition MaxWidth="150"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.ColumnSpan="2" Text="{Binding Path=Titre}" Margin="5,0,5,0" FontSize="18" FontWeight="Bold" Foreground="White" TextWrapping="Wrap" FontFamily="Arial" HorizontalAlignment="Left" />
<local:ClickableImageButton Grid.Row="1" Tag="{Binding Path=Id}" Grid.Column="0" ImpostorClick="Image_Click" Margin="10">
<local:ClickableImageButton.Content>
<local:ClickableImage Source="Content/tada.png" />
</local:ClickableImageButton.Content>
</local:ClickableImageButton>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=Texte}" Margin="10,0,10,0" FontSize="16" Foreground="White" TextWrapping="Wrap" FontFamily="Arial" VerticalAlignment="Center" HorizontalAlignment="Left" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

So finally i get it to work. That wasn't due to the fact that i was deriving from UserControl.
So i kept deriving BaseImpostorButton from UserControl, i emptyed the ContentPresenter in the ControlTemplate (<ContentPresenter />).
I didn't have to set the DefaultStyleKey.
I just had to remove any content from the child class xaml file. Indeed, when i created my child UserControl, i didn't removed the default content added, that is <Grid />. Removing this just solved all my problems.
Looks like the default Content is not overriden when we try to set it from a templated context, but only when set from a non templated context.
ie Former code:
<sk:BaseImpostorButton x:Class="Compteur_3D.ClickableImageButton"
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">
<Grid/>
</sk:BaseImpostorButton>
revised code:
<sk:BaseImpostorButton x:Class="Compteur_3D.ClickableImageButton"
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">
</sk:BaseImpostorButton>
Edit: At runtime, my ClickableImageButton element has the right content (ie ClickableImage) when the <Grid /> is removed. BUT when <Grid /> is not removed, my ClickableImageButton has the empty Grid as content... As if this <Grid /> was not overriden when setting the content in:
<local:ClickableImageButton ImpostorClick="Image_Click" Margin="10">
<local:ClickableImageButton.Content>
<local:ClickableImage Source="{Binding Path=Image.Source}" />
</local:ClickableImageButton.Content>
</local:ClickableImageButton>
Edit: Target Framework 4 Client Profile

Related

How to resize button content in WPF with a viewbox while maintaining the Font size?

I am creating an app and I need the content of a button to be resizable when the user minimises their screen. We know that the viewbox does this in WPF; it's the easiest way to resize text automatically.
This is the code for [the top part] of the button, I apologise about the formatting:
<Button Grid.Row="0"
Grid.Column="2"
Background="#3767B0"
Style="{DynamicResource IconStyle}"
BorderBrush="Transparent">
<Button.ContentTemplate>
<DataTemplate >
<Viewbox>
<TextBlock></TextBlock>
</Viewbox>
</DataTemplate>
</Button.ContentTemplate>
</Button>
What I want to get out of this is: to use the Viewbox in WPF to resize the content of this button while maintaining the font size of the content.
This resizes the content of the button, but the button's content is not maintained:
This is how it should look like with a viewbox, and should resize properly:
By maintaining I mean I want to use the viewbox whilst the content of the button (which is a child of the viewbox) looks exactly how it would've with a font size of 22. You can see how I want it to look like with a viewbox inside the content of the button in the image above. I've tried to be as clear as possible on this. Maybe I don't understand how the viewbox works?
Someone requested the icon style. Here is the icon style code:
<Style TargetType="Button"
x:Key="IconStyle"
BasedOn="{StaticResource ButtonStyle1}">
<Setter Property="FontFamily"
Value="Segoe MDL2 Assets" />
<Setter Property="Grid.RowSpan"
Value="2" />
<Setter Property="Padding"
Value="0,0,0,60" />
<Setter Property="Foreground"
Value="White" />
<Setter Property="FontSize"
Value="80" />
<Setter Property="Background"
Value="#307A85" />
<Setter Property="BorderBrush"
Value="Transparent" />
<Setter Property="BorderThickness"
Value="0" />
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect BlurRadius="15"
ShadowDepth="0"
Opacity="0.4"
Color="Black" />
</Setter.Value>
</Setter>
If I understand correctly what you need to implement, then remove the ViewBox and set the explicit dimensions of the TextBlock.
I am showing an arbitrary example, but for your task, you yourself choose the required dimensions and alignment.
<Button Background="#3767B0"
Style="{DynamicResource IconStyle}"
BorderBrush="Transparent">
<Button.ContentTemplate>
<DataTemplate >
<TextBlock Width="300"
Height="300"
FontSize="200"
Text=""/>
</DataTemplate>
</Button.ContentTemplate>
</Button>
Hello my good friends on Stack OverFlow. I have found a solution to this problem, all I had to do was set the padding of the TextBlock:
<!--FEEDBACK BUTTON-->
<Button Grid.Row="3"
Grid.Column="2"
Grid.RowSpan="2"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
BorderThickness="3"
Name="Feedback_Button"
BorderBrush="White"
Click="Button_Click"
MouseEnter="Button_MouseEnter"
MouseLeave="Button_MouseLeave">
<Button.Template>
<ControlTemplate TargetType="Button">
<ContentPresenter Content="{TemplateBinding Content}" />
</ControlTemplate>
</Button.Template>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="218*" />
<RowDefinition Height="68*" />
</Grid.RowDefinitions>
<Button Grid.Row="0"
Grid.Column="2"
Background="#3767B0"
FontFamily="Segoe MDL2 Assets"
Foreground="White"
Content="Feedback"
BorderBrush="Transparent">
<Button.ContentTemplate>
<DataTemplate>
<Viewbox>
<TextBlock Padding="15"></TextBlock>
</Viewbox>
</DataTemplate>
</Button.ContentTemplate>
</Button>
<Button Grid.Row="4"
Grid.Column="2"
Background="#FF2D5BA0"
FontFamily="Segoe UI Light"
Style="{StaticResource TextButton}"
Content="Feedback"
BorderBrush="Transparent">
<Button.ContentTemplate>
<DataTemplate>
<Viewbox>
<TextBlock Padding="15">Feedback</TextBlock>
</Viewbox>
</DataTemplate>
</Button.ContentTemplate>
</Button>
</Grid>
</Button>
<!--FEEDBACK BUTTON-->
Thank you my friends for your help, such a simple solution I would've expected you guys to know this.
Cheers,
#Tom Joney , I do not quite clearly understand what you need to implement, so I cannot give an exact answer.
General answer for using different layout.
The ViewBox scales the content to the maximum allowed size provided by the outer container.
The Padding property of a container sets the size of the border between the container and its contents.
The element's Margin property sets the size of the border between the element and its containing container.
That is, these are very close properties.
In our case, the main content is Text.
Therefore, there is no difference how to set the size of the border: between the Text and the containing TextBlock (TextBlock.Padding) or between the TextBlock and its containing outer container (the Grid line).
Look at two examples in which I set the background colors for better clarity.
Example with Padding
<Window x:Class="ViewBoxScaleText.PaddingWind"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ViewBoxScaleText"
mc:Ignorable="d"
Title="PaddingWind" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border Background="LightGreen">
<Viewbox>
<TextBlock Padding="15"
Background="LightBlue"
Text="{Binding Text, ElementName=tb}"/>
</Viewbox>
</Border>
<TextBox x:Name="tb" Grid.Row="1" Margin="10" Text="Feedback"/>
</Grid>
</Window>
Example with Margin
<Window x:Class="ViewBoxScaleText.MarginWind"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ViewBoxScaleText"
mc:Ignorable="d"
Title="MarginWind" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border Background="LightGreen">
<Viewbox>
<TextBlock Margin="15"
Background="LightBlue"
Text="{Binding Text, ElementName=tb}"/>
</Viewbox>
</Border>
<TextBox x:Name="tb" Grid.Row="1" Margin="10" Text="Feedback"/>
</Grid>
</Window>
The color of the regions shows that the containers have different sizes, but this does not affect the location and size of the Text.
Try to enter text in the field at the bottom of the window to see how the amount of text affects its size and the size of the border.
Since the ViewBox scales the entire content, both the text size size and are the border scaled.
If in the examples above you change the size of the window, you will see that the size of the container occupied by the text also changes.
This happens due to the fact that the setting of the border occurs inside the ViewBox and thus we set the size of the border, in fact, in units relative to the size of the text.
Changing the size of the text will change the size of the face and therefore change the overall container for the text.
Here is an example with the ability to change the font size in the very bottom margin of the window.
See how this affects the size of the border.
<Window x:Class="ViewBoxScaleText.FontSizeWind"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ViewBoxScaleText"
mc:Ignorable="d"
Title="FontSizeWind" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border Background="LightGreen">
<Viewbox>
<TextBlock Margin="15"
Background="LightBlue"
Text="{Binding Text, ElementName=tbText}" FontSize="{Binding Text, ElementName=tbFontSize}"/>
</Viewbox>
</Border>
<TextBox x:Name="tbText" Grid.Row="1" Margin="10" Text="Feedback"/>
<TextBox x:Name="tbFontSize" Grid.Row="2" Margin="10" Text="80"/>
</Grid>
</Window>
Here are some more layout options in one XAML so that you can launch, check their behavior and choose the one that suits you
<Window x:Class="ViewBoxScaleText.MultiVariantWind"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ViewBoxScaleText"
mc:Ignorable="d"
Title="MultiVariantWind" Height="750" Width="400">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border Background="LightGreen" Margin="5">
<Viewbox>
<TextBlock Margin="15"
Background="LightBlue"
Text="{Binding Text, ElementName=tbText}" FontSize="{Binding Text, ElementName=tbFontSize}"/>
</Viewbox>
</Border>
<Border Background="LightGreen" Margin="5" Grid.Row="1">
<Viewbox Margin="15">
<TextBlock
Background="LightBlue"
Text="{Binding Text, ElementName=tbText}" FontSize="{Binding Text, ElementName=tbFontSize}"/>
</Viewbox>
</Border>
<Border Background="LightGreen" Margin="5" Grid.Row="2">
<Viewbox Width="150" Height="150">
<TextBlock
Background="LightBlue"
Text="{Binding Text, ElementName=tbText}" FontSize="{Binding Text, ElementName=tbFontSize}"/>
</Viewbox>
</Border>
<Border Background="LightGreen" Margin="5" Grid.Row="3">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="15*"/>
<ColumnDefinition Width="70*"/>
<ColumnDefinition Width="15*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="15*"/>
<RowDefinition Height="70*"/>
<RowDefinition Height="15*"/>
</Grid.RowDefinitions>
<Viewbox Grid.Row="1" Grid.Column="1">
<TextBlock
Background="LightBlue"
Text="{Binding Text, ElementName=tbText}" FontSize="{Binding Text, ElementName=tbFontSize}"/>
</Viewbox>
</Grid>
</Border>
<TextBox x:Name="tbText" Grid.Row="4" Margin="10" Text="Feedback"/>
<TextBox x:Name="tbFontSize" Grid.Row="5" Margin="10" Text="80"/>
</Grid>
</Window>

How to center UserControl in a TabControl

My MainWindow is built with TabContol containing in each tab UserControl in xaml files. Opening specific UserControl is not a problem, but aligning it is. I was able to horizontally center content of tab but struggle to vertically do this same. I found out that the root problem is that UserControl don't take the whole free space (height) in the Tab. I tried to make main grid VerticalAlignment="Stretch" and "Center" but that didn't help. I could use margin with specific number or define row fixed hight but that will not work on every resolution and I don't want to write method in code behind but use the power of xaml. How can I force UserControl to take whole height in Tab and then vertically center it (it's important to do it for specific UserControl because others should have default position)?
ps. I'm using MetroWindow from MahApps.Metro.
MainWindow main Grid:
<Grid>
<StackPanel>
<TabControl ItemsSource="{Binding Tabs}"
SelectedIndex="0">
<TabControl.Resources>
<Style TargetType="{x:Type TabPanel}">
<Setter Property="HorizontalAlignment"
Value="Center" />
</Style>
<DataTemplate DataType="{x:Type VMod:LoginViewModel}">
<Pages:LoginView />
</DataTemplate>
<DataTemplate DataType="{x:Type VMod:AdminViewModel}">
<Pages:AdminView />
</DataTemplate>
<DataTemplate DataType="{x:Type VMod:ProductsViewModel}">
<Pages:ProductsView />
</DataTemplate>
<DataTemplate DataType="{x:Type VMod:DistributionViewModel}">
<Pages:DistributionView />
</DataTemplate>
<DataTemplate DataType="{x:Type VMod:SummaryViewModel}">
<Pages:SummaryView />
</DataTemplate>
<DataTemplate DataType="{x:Type VMod:SettingsViewModel}">
<Pages:SettingsView />
</DataTemplate>
</TabControl.Resources>
<TabControl.ItemTemplate>
<DataTemplate DataType="{x:Type inter:ITab}">
<TextBlock>
<Run Text="{Binding TabName}" />
</TextBlock>
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
</StackPanel>
</Grid>
UserControl main Grid:
<Grid Background="LightBlue"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Height="300"
Width="300"
Grid.Row="2"
BorderBrush="LightGray"
BorderThickness="1">
<StackPanel HorizontalAlignment="Center">
<iconPacks:PackIconRPGAwesome Kind="Honeycomb"
HorizontalAlignment="Center"
Width="60"
Height="60"
Margin="0, 0, 0, 0"/>
<TextBlock HorizontalAlignment="Center"
Text="DistributionTool"
FontSize="20"
FontWeight="Bold"
Margin="5" />
<Grid Width="200">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0"
Margin="5"
TextAlignment="Left"
FontSize="15"/>
<iconPacks:PackIconMaterial Grid.Column="1"
Kind="AccountTie"
Width="20"
Height="20"
VerticalAlignment="Center"/>
</Grid>
<Grid Width="200">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<PasswordBox Grid.Column="0"
Margin="5"
HorizontalContentAlignment="Left"
FontSize="15"
Style="{StaticResource Win8MetroPasswordBox}" />
<iconPacks:PackIconMaterial Grid.Column="1"
Kind="Key"
Width="20"
Height="20"
VerticalAlignment="Center" />
</Grid>
<Button Content="LOGIN"
Width="80"
metro:ControlsHelper.ContentCharacterCasing="Normal"
Margin="5"
Style="{StaticResource AccentedSquareButtonStyle}" />
</StackPanel>
</Border>
</Grid>
From what I gather, what you could try would be:
Remove the StackPanel in your MainWindow Grid. Unless you intend to have more than 1 child inside the stack panel (Other than your TabControl), it is useless.
Add VerticalAlignement="Stretch" to your TabControl. This will allow it to take up all the space it can vertically.
Then you should be pretty much set to go.
The reason why you shouldn't use a StackPanel unless you intend to stack items inside, as in
<StackPanel>
<Child1/>
<Child2/>
</StackPanel>
is that the StackPanel.Orientation property affects how things will appear inside, including the Alignement of each child.
So Orientation="Vertical" (the default), affects the VerticalAlignement of its children. Same idea with Horizontal.

Flickering and blurry text

I have an issue with a text. In some custom usercontrols it is flickering every more/less second (probably when rendering) here is a gif:
I'm using these render and text options for now which are applied on Window:
RenderOptions.ClearTypeHint="Enabled"
TextOptions.TextFormattingMode="Display"
RenderOptions.BitmapScalingMode="HighQuality"
I was using these before:
RenderOptions.ClearTypeHint="Enabled"
RenderOptions.BitmapScalingMode="Linear"
TextOptions.TextRenderingMode="Grayscale"
TextOptions.TextFormattingMode="Display"
and it was ok but the text was too sharp.
XAML of this specific component:
<UserControl x:Class="FunctionButton" x:Name="PART_Base"
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"
xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" xmlns:ViewModels="clr-namespace:SkyPCTool"
xmlns:materialDesign="clr-namespace:MaterialDesignThemes.Wpf;assembly=MaterialDesignThemes.Wpf"
mc:Ignorable="d"
TextElement.FontWeight="Medium"
TextElement.FontSize="14"
FontFamily="pack://application:,,,/MaterialDesignThemes.Wpf;component/Resources/Roboto/#Roboto"
MinHeight="52" d:DesignWidth="300" Margin="0">
<UserControl.DataContext>
<ViewModels:FunctionButtonViewModel/>
</UserControl.DataContext>
<UserControl.Resources>
<ViewModels:TextToVisibilityConverter x:Key="textConverter" />
</UserControl.Resources>
<Border CornerRadius="2" Background="{StaticResource MaterialDesignPaper}">
<Grid Margin="12,6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<Button x:Name="PART_Button" HorizontalAlignment="Center" VerticalAlignment="Center" Padding="12,6" Content="{Binding ButtonCaption}" />
<Grid Grid.Column="1" Margin="6,0">
<Image Source="{Binding Icon}" ToolTip="{Binding IconTag}" />
</Grid>
<Grid Grid.Column="2" SnapsToDevicePixels="True">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding Title}" RenderOptions.ClearTypeHint="Enabled" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" FontSize="14" />
<TextBlock Grid.Row="1" Text="{Binding Description}" RenderOptions.ClearTypeHint="Enabled" Margin="12,0,0,0" Visibility="{Binding Text, RelativeSource={RelativeSource Self}, Converter={StaticResource textConverter}}" FontWeight="Normal" VerticalAlignment="Center" TextWrapping="Wrap" FontSize="12.667" />
</Grid>
</Grid>
</Border>
I did it. I downloaded the Roboto font from Google website, then I set these options on Window:
RenderOptions.ClearTypeHint="Enabled"
TextOptions.TextFormattingMode="Ideal"
TextOptions.TextHintingMode="Animated"
TextOptions.TextRenderingMode="ClearType"

WPF - How to skip a label in tab navigation?

I have a stackpanel inside a controltemplate inside a itemscontrol inside a stackpanel inside a grid inside a usercontrol (se the xaml below). In the inner stackpanel there is a label (Name="NoComponentChosen") and another stackpanel (Name="ComponentChosen"). The label's visibility is initially collapsed.
The controltemplate has a datatrigger with a binding. When the binding reference has a specific value the label (NoComponentChosen) becomes visible and the stackpanel collapses.
I would like to skip the label/stackpanel when I am tabbing trough the user interface. I would also like to still be able tab through the rest of the things in my ChangeRequestView.xaml (listbox and buttons).
Right now - when I tab - the label/stackpanel eventually becomes chosen and is surrounded by a dotted rectangle. That is what I would like to avoid.
This is my ChangeRequestView.xaml:
<UserControl x:Class="MyProgram.View.ChangeRequestView"
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"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:ListBoxBehavior="clr-namespace:MyProgram.Utility"
mc:Ignorable="d"
d:DesignHeight="500" d:DesignWidth="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="35"/>
<RowDefinition Height="45*"/>
<RowDefinition Height="10*"/>
<RowDefinition Height="20*"/>
<RowDefinition Height="35"/>
</Grid.RowDefinitions>
<!--The title of the view-->
<Label Grid.Row="0" Content="Change Requests" FontWeight="Bold" Margin="5,5,5,5" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<!--The component chosen-->
<StackPanel Grid.Row="1" Orientation="Horizontal" Margin="5,0,0,0" IsHitTestVisible="False" Focusable="False">
<ItemsControl>
<ItemsControl.Template>
<ControlTemplate>
<StackPanel>
<StackPanel Name="ComponentChosen" Orientation="Horizontal">
<Label Content="Reference des.: " />
<Label Name="referenceDesignation" Content="{Binding Path=ReferenceDesignation, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
<Label Name="NoComponentChosen" Content="Choose a component" Visibility="Collapsed"/>
</StackPanel>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding ReferenceDesignation}" Value="">
<Setter TargetName="ComponentChosen" Property="Visibility" Value="Collapsed"/>
<Setter TargetName="NoComponentChosen" Property="Visibility" Value="Visible"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ItemsControl.Template>
</ItemsControl>
</StackPanel>
<ListBox Grid.Row="2" ... />
<Button Grid.Row="3" ... />
<Button Grid.Row="4" ... />
</Grid>
</UserControl>
The whole UserControl/ChangeRequestView.xaml is part of my MainWindow - I don't know if that has anything to say. I tab through all of the different views in my MainWindow, and when I get to the ChangeRequestView I would like to skip the label/stackpanel according to which of them isn't collapsed.
This is my MainWindow.xaml:
<Window x:Class="MyProgram.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:view="clr-namespace:MyProgram.View"
xmlns:vm="clr-namespace:MyProgram.ViewModel"
...>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="309*"/>
<RowDefinition Height="187*"/>
<RowDefinition Height="120*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="209*"/>
<ColumnDefinition Width="558*"/>
<ColumnDefinition Width="250*"/>
</Grid.ColumnDefinitions>
<Menu IsMainMenu="True" Name="Menu1" VerticalAlignment="Top" Grid.Row="0" Grid.ColumnSpan="3">
<MenuItem Header="_File">
<MenuItem Header="_Save changed change requests for current reference designation"
InputGestureText="Ctrl+S" Command="{Binding Path=HotKeysSaveChangeRequestUpdateCmd}"/>
<MenuItem Header="_Upload change requests for current project"
InputGestureText="Ctrl+U" Command="{Binding Path=HotKeysUploadCmd}"/>
<MenuItem Header="_Exit" ToolTip="Exit this program"
InputGestureText="CTRL+X" Command="{Binding Path=ShutDownCmd}"/>
</MenuItem>
</Menu>
<!--Search Region-->
<Border Grid.Row="2" Grid.Column="0" Grid.RowSpan="2" Margin="3,1,1,3" BorderThickness="2,2,2,2" CornerRadius="4,4,4,4" BorderBrush="LightGray">
<view:SearchView x:Name="SearchView"/>
</Border>
<!-- Project Region -->
<Border Grid.Row="1" Grid.Column="0" Margin="3,3,1,1" BorderThickness="2,2,2,2" CornerRadius="4,4,4,4" BorderBrush="LightGray">
<view:ProjectView x:Name="ProjectView" />
</Border>
<!-- Components Region -->
<Border Grid.Row="1" Grid.Column="1" Grid.RowSpan="2" Margin="1,3,1,1" BorderThickness="2,2,2,2" CornerRadius="4,4,4,4" BorderBrush="LightGray">
<view:ComponentView x:Name="ComponentView" />
</Border>
<!-- Change Request Region -->
<Border Grid.Row="1" Grid.Column="2" Grid.RowSpan="2" Margin="1,3,3,1" BorderThickness="2,2,2,2" CornerRadius="4,4,4,4" BorderBrush="LightGray">
<view:ChangeRequestView x:Name="ChangeRequestView" />
</Border>
<!-- Log Region -->
<Border Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" Margin="1,1,3,3" BorderThickness="2,2,2,2" CornerRadius="4,4,4,4" BorderBrush="LightGray">
<view:LogView x:Name="LogView" />
</Border>
</Grid>
<Window.InputBindings>
<KeyBinding Gesture="CTRL+U" Command="{Binding Path=HotKeysUploadCmd}"/>
<KeyBinding Gesture="CTRL+S" Command="{Binding Path=HotKeysSaveChangeRequestUpdateCmd}"/>
<KeyBinding Gesture="CTRL+X" Command="{Binding Path=ShutDownCmd}"/>
</Window.InputBindings>
</Window> </br>
I apologize for the long xaml-files, but I'm thinking the more information I provide to you the easier it will be for you to help me solve this tabbing issue.
Do you have any ideas of how to skip the label "NoComponentChosen"/the stackpanel "ComponentChosen" when I tab through the user interface?
Try KeyboardNavigation.TabNavigation Attached Property with KeyboardNavigationMode.None on the container with the elements you want to skip.
KeyboardNavigation.TabNavigation="None"

Using HierarcicalDataTemplates in conjunction with TreeViewItem control templates

I am having some difficulty figuring out how to template the following TreeView item layout:
I have several items, SearchList, which contains a collection of Search, which contains a collection of DataSet (sort of, but that is beside the point). What I am having difficulty with is styling each node level the way I want. I am using MVVM, and the TreeViews ItemsSource property is set to an ObservableCollection of SearchListViewModels which in turn contain my objects all the way down the object tree.
I can successfully style the SearchList HierarchicalDataTemplate to display them correctly. Where I get hung up is on SearchTerm nodes styling. I want the DataSets to be represented in a wrap panel or uniform grid (I haven't decided yet) to the right of the SearchTerm content area. I have modified a TreeViewItem control template to behave this way I think), however if I set it in the ItemContainerStyle property of the Search HierarchicalDataTemplate, it does nothing. All that gets displayed is the content for the Search.
My Altered TreeViewItem Template
<Style TargetType="{x:Type TreeViewItem}" x:Key="AlteredTreeViewItem">
<Setter Property="HorizontalContentAlignment"
Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"
MinWidth="19" />
<ColumnDefinition Width="0.414*" />
<ColumnDefinition Width="0.586*"/>
</Grid.ColumnDefinitions>
<Border x:Name="Bd" HorizontalAlignment="Stretch"
Grid.Column="1" Grid.ColumnSpan="1" Background="#7F058956">
<ContentPresenter x:Name="PART_Header" Margin="10,0" />
</Border>
<WrapPanel x:Name="ItemsHost"
Grid.Column="2" IsItemsHost="True"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
My Search Hierarchical Data Template
<HierarchicalDataTemplate DataType="{x:Type local:SearchViewModel}" ItemsSource="{Binding MySearch.Custodians}" ItemContainerStyle="{StaticResource AlteredTreeViewItem}">
<TextBlock Text="{Binding MySearch.SearchName}" Foreground="Black" FontFamily="Arial" FontSize="16"/>
</HierarchicalDataTemplate>
Surely it is possible to both style differently and have child items laid out differently? How can this be achieved?
It seems that you are pretty close to what you're after. I tried to recreate your scenario based on the code you posted and I noted some problems with it (which of course are based on my interpretation of the code you posted)
You are missing the ContentSource="Header" part of the ContentPresenter
I think you are applying the ItemContainerStyle at the wrong HierarchicalDataTemplate level. It should be specified on the parent in order to affect the children (in your case SearchListViewModel).
The default Template for TreeViewItem lays out the ContentPresenter in an Auto sized ColumnDefinition so the WrapPanel won't succesfully wrap unless you modify the ItemContainerStyle for the parent as well. I changed it to a UniformGrid in my sample below
With the changes from above and a few other things I got a result that looks like this which hopefully is pretty close to what you're after
I uploaded the sample solution here: https://www.dropbox.com/s/4v2t8imikkagueb/TreeViewAltered.zip?dl=0
And here is the Xaml code for it (too much code to post it all..)
<Window.Resources>
<!-- DataSet-->
<HierarchicalDataTemplate DataType="{x:Type data:DataSet}">
<Border BorderThickness="3"
BorderBrush="Gray"
Background="Green">
<TextBlock Text="{Binding Path=Tables[0].TableName}"
Margin="5"/>
</Border>
</HierarchicalDataTemplate>
<!-- SearchViewModel -->
<HierarchicalDataTemplate DataType="{x:Type viewModel:SearchViewModel}"
ItemsSource="{Binding DataSets}">
<TextBlock Text="{Binding DisplayName}"
Foreground="Black"
FontFamily="Arial"
FontSize="16"/>
</HierarchicalDataTemplate>
<!-- SearchListViewModel -->
<HierarchicalDataTemplate DataType="{x:Type viewModel:SearchListViewModel}"
ItemsSource="{Binding SearchList}">
<HierarchicalDataTemplate.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="19" />
<ColumnDefinition Width="0.414*" />
<ColumnDefinition Width="0.586*"/>
</Grid.ColumnDefinitions>
<Border x:Name="Bd"
HorizontalAlignment="Stretch"
Grid.Column="1"
Grid.ColumnSpan="1"
Background="#7F058956">
<ContentPresenter x:Name="PART_Header"
ContentSource="Header"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
</Border>
<UniformGrid x:Name="ItemsHost"
Grid.Column="2"
Columns="3"
IsItemsHost="True"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</HierarchicalDataTemplate.ItemContainerStyle>
<TextBlock Text="{Binding DisplayName}"
FontSize="20"/>
</HierarchicalDataTemplate>
</Window.Resources>
<Grid>
<TreeView ItemsSource="{Binding SearchListViewModels}" />
</Grid>
Something I learnt a long time ago when trying to create a similar interface was that you are better using a ListBox than a TreeView.
Why?
If you only have one level of expansion (as it appears from your sample) you will a lot more control of the layout as you have a single DataTemplate to style.
It is lot easier to customize a ListBox than a TreeView as you do not have be concerned with the GridViewColumnHeader and GridViewColumnPresenters etc.
To get the expansion part (which is why you initially selected a TreeView), simply use a Grid with two rows defined and an Expander in the second row bound to the IsChecked property of a ToggleButton. See the example that I pulled from my Log Viewer.
<DataTemplate>
<Grid Margin="0,0,0,3" Grid.IsSharedSizeScope="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30" SharedSizeGroup="SSG_TimeIcon"/>
<ColumnDefinition Width="120" SharedSizeGroup="SSG_Time"/>
<ColumnDefinition Width="30" SharedSizeGroup="SSG_LevelIcon"/>
<ColumnDefinition Width="70" SharedSizeGroup="SSG_Level"/>
<ColumnDefinition Width="*" SharedSizeGroup="SSG_Message"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- ProgramTime -->
<Rectangle Grid.Column="0" Grid.Row="0" Margin="0,0,0,0" Width="16" Height="16" VerticalAlignme="Top" HorizoalAlignme="Stretch" Fill="{StaticResource Icon_Timer}"/>
<TextBlock Grid.Column="1" Grid.Row="0" Margin="5,0,0,0" VerticalAlignme="Top" HorizoalAlignme="Stretch" Text="{Binding Path=TimeStamp, Converter={StaticResource ObjectToStringConverter}}" ToolTip="{Binding Path=ProgramTime}"/>
<!-- Level -->
<Rectangle Grid.Column="2" Grid.Row="0" Margin="10,0,0,0" Width="16" Height="16" VerticalAlignme="Top" HorizoalAlignme="Stretch" Fill="{Binding Path=Level, Converter={StaticResource MappingConverterNinjaLogLevelEnumToBrushResource}}"/>
<TextBlock Grid.Column="3" Grid.Row="0" Margin="5,0,0,0" Text="{Binding Path=LevelFriendlyName}" VerticalAlignme="Top" HorizoalAlignme="Stretch"/>
<!-- Message -->
<StackPanel Grid.Column="4" Grid.Row="0" Margin="10,0,0,0" Orieation="Horizoal" >
<TextBlock Margin="0,0,0,0" Text="{Binding Path=LogMessage}" TextWrapping="Wrap" VerticalAlignme="Top" HorizoalAlignme="Stretch"/>
<ToggleButton x:Name="ExpandExceptiooggleButton" VerticalAlignme="Top" Margin="5,0,0,0" IsChecked="False"
Coe="Show Details" Tag="Hide Details" Style="{StaticResource TextButtonStyle}"
Foreground="{StaticResource BlueBrush}" Background="{StaticResource RedBrush}"
Visibility="{Binding Path=HasException, Converter={StaticResource BoolToVisibilityConverter}}" />
</StackPanel>
<Expander IsExpanded="{Binding Path=IsChecked, ElemeName=ExpandExceptiooggleButton}" Style="{StaticResource CoeExpanderStyle}"
Margin="10,0,0,0" Grid.Column="4" Grid.Row="1">
<Border BorderBrush="{StaticResource DarkGreyBrush}" BorderThickness="1,0,0,0">
<TextBlock Text="{Binding Path=Exception}" Margin="5,0,0,0"/>
</Border>
</Expander>
</Grid>
</DataTemplate>
Can you see how much easier it is to define a header and expandable body. If you do have a need for nested data, add a Level property your view model (you are using MVVM aren't you?!) and then create a IValueConverter that returns a Margin (i.e. Thickness) to fake the indent.

Resources