Include a UserControl with Content - wpf

I've created a UserControl. I would like to include it with this code:
<UserControl1 Header="Heading">
<TextBlock Text="My Content" />
</UserControl1>
That's the UserControl:
<UserControl x:Class="WpfApplication1.UserControl1"
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" MinHeight="200"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<Style TargetType="ToggleButton">
<!-- ... -->
</Style>
</UserControl.Resources>
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=Header}" Grid.Column="0" />
<ToggleButton Name="ToggleButton" IsChecked="True" Grid.Column="2" />
</Grid>
<Rectangle Stroke="#c3c3c3" StrokeThickness="1" Height="1" StrokeDashArray="4 4" SnapsToDevicePixels="True" Focusable="False" />
<!-- Content -->
<ContentControl>
<ContentPresenter/>
</ContentControl>
</StackPanel>
</UserControl>
Now to my problem:
If I integrate it with the following code,
<UserControl1 Header="Heading">
<TextBlock Text="My Content" />
</UserControl1>
I receive that as result:
That's not what I want.
But when i integrate it with this code, I've got the desired result.
<UserControls:UserControl1 Header="Heading" />
What's wrong at my first way?

In order to get things working as you expect you would have to set the UserControl's Template:
<UserControl x:Class="UserCtrl.UserControl1"
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">
<UserControl.Template>
<ControlTemplate TargetType="UserControl">
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="{Binding Path=Header,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=UserControl}}}" />
<ToggleButton Name="ToggleButton" IsChecked="True" Grid.Column="2" />
</Grid>
<Rectangle Stroke="#c3c3c3" StrokeThickness="1" Height="1" StrokeDashArray="4 4" SnapsToDevicePixels="True" Focusable="False" />
<!-- Content -->
<ContentPresenter/>
</StackPanel>
</ControlTemplate>
</UserControl.Template>
<!-- Initial Content of the UserControl -->
<TextBlock Text="Initial Content"/>
</UserControl>

There is nothing wrong with the first way. It simply creates a UserControl1 and sets the content to a TextBlock, hereby overriding the content you set in the definition. The second way creates a UserControl1 and leaves the content as is.

Related

Change the size of checkbox rectangle without changing its content

In my following WPF app, how can we change the size of the CheckBox without changing the size of its content (an Segoe MDL2 Assets icon). I would like to see the checkbox rectangle to be the half the size of its content (an icon). If I set the width and height of the checkbox to 10 it reduces the content size (icon) as well:
<Window x:Class="WpfApp1.MainWindow"
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:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<StackPanel Margin="10">
<Label FontWeight="Bold">Application Options</Label>
<CheckBox VerticalContentAlignment="Center">
<TextBlock Text="" FontFamily="Segoe MDL2 Assets" FontSize="20"/>
</CheckBox>
</StackPanel>
</Grid>
</Window>
Display of the above XAML:
You could move the TextBlock out of the CheckBox. Something like this:
<StackPanel Margin="10">
<Label FontWeight="Bold">Application Options</Label>
<Grid VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<CheckBox RenderTransformOrigin="0.5,0.5" VerticalAlignment="Center">
<CheckBox.RenderTransform>
<ScaleTransform ScaleX="0.5" ScaleY="0.5" />
</CheckBox.RenderTransform>
</CheckBox>
<TextBlock Grid.Column="1" Text="" FontFamily="Segoe MDL2 Assets" FontSize="20"/>
</Grid>
</StackPanel>

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"

UserControl content is empty when trying to use ContentPresenter inside DataTemplate

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

How to display xamlcode in my usercontrol

I have created user control. I want to display XAML inside my usercontrol. Like that:
<UserControls:UserControl1 Header="Heading">
<TextBlock Text="My Content" />
</UserControls:UserControl1>
Thats the usercontrol:
<UserControl x:Class="UserControls.UserControl1"
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" MinHeight="200"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<Style TargetType="ToggleButton">
<!-- ... -->
</Style>
</UserControl.Resources>
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=Header}" Grid.Column="0" />
<ToggleButton Name="ToggleButton" IsChecked="True" Grid.Column="2" />
</Grid>
<Rectangle Stroke="#c3c3c3" StrokeThickness="1" Height="1" StrokeDashArray="4 4" SnapsToDevicePixels="True" Focusable="False" />
<!-- Content -->
</StackPanel>
</UserControl>
Now how can I set the xaml code (e.g. <TextBlock Text="My Content" />), in my control?
You just need to add a ContentPresenter or ItemsPresenter depending on the item the presenter is added to.
In your case, if you wanted the content in the stack panel below the other items, you could place a Content Control and add a ContentPresenter inside like so.
<StackPanel...>
<Grid ...>
...
</Grid>
<Rectangle .../>
<!---Content here-->
<ContentControl>
<ContentPresenter/>
</ContentControl>
</StackPanel>
If you only wanted to support more than one content item, then use some control that suports more than one content, and use <ItemsPresenter/> instead.

WPF - Usercontrol as ListItemTemplate not filling listbox width

Just trying to get my head round WPF. I have a usercontrol which I'm using as the template for items in a listbox, however no matter what I try the usercontrol's width is always shrinking to the minimum size but I want it to fill the available width. I've found a similar query on here but it was relating just to a usercontrol not within a listbox and the solution proposed doesn't apply here.
My UserControl is defined as :
<UserControl x:Class="uReportItem"
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="60" d:DesignWidth="300">
<Grid >
<Border CornerRadius="3,3,3,3" BorderBrush="#0074BA" BorderThickness="1" Background="#00D6F9" Margin="0">
<DockPanel Margin="3,3,3,3">
<Grid Height="Auto">
<!-- Grid Definition-->
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<!-- Content -->
<!-- Top Row-->
<Button Grid.RowSpan="2">Delete</Button>
<StackPanel Orientation="Horizontal" Grid.Column="1">
<Label x:Name="Heading" Content="{Binding Heading}" FontSize="14" FontWeight="bold"></Label>
<Label x:Name="Subheading" Content="{Binding SubHeading}" FontSize="14"></Label>
</StackPanel>
<Button Grid.Column="2">Blah</Button>
<!-- Second Row-->
<Label Grid.Row="1" Grid.Column="1" x:Name="Comments">Comments</Label>
<Button Grid.Column="2">Blah</Button>
</Grid>
</DockPanel>
</Border>
</Grid>
And the implementation on the window is :
<Window x:Class="vReport"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:RecorderUI"
Title="vReport" Height="300" Width="300" Background="#00BCF0">
<Window.Resources>
<DataTemplate x:Key="Record" DataType="ListItem">
<Grid>
<local:uReportItem></local:uReportItem>
</Grid>
</DataTemplate>
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<local:uReport Margin="5" Grid.Row="0"></local:uReport>
<Border Grid.Row="1" BorderBrush="#0074BA" CornerRadius="3">
<ListBox Margin="5" Background="#00D6F9" BorderBrush="#0074BA" x:Name="ListRecords" ItemsSource="{Binding Items}" ItemTemplate ="{StaticResource Record}"></ListBox>
</Border>
<TextBlock Grid.Row="2" x:Name="SelectedItem" Text="{Binding Path=SelectedItem.Heading, Mode=TwoWay}"></TextBlock>
</Grid>
Any ideas?
Try setting HorizontalContentAlignment to Stretch on the ListBox:
<ListBox Margin="5" Background="#00D6F9" BorderBrush="#0074BA" x:Name="ListRecords" ItemsSource="{Binding Items}" ItemTemplate ="{StaticResource Record}" HorizontalContentAlignment="Stretch"></ListBox>

Resources