UserControl in DataTemplate doesn't applied style for font - wpf

I have a user control in a DataTemplate, The Style of a TextBlock doesn't change the FontSize but changes the Background.
Attached are the samples:
Create a WPF window.
Create a User control, UserControl1
Inside the Window paste the below code:
<Window.Resources>
<Style TargetType="{x:Type TextBlock}"
x:Key="TextBlockStyleFontAndBackgound">
<Setter Property="FontSize"
Value="20" />
<Setter Property="Background"
Value="Blue" />
</Style>
<DataTemplate x:Key="contentTemplate">
<StackPanel>
<m:UserControl1 />
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<ContentControl FontSize="10">
<StackPanel x:Name="stackPanel">
<Button Click="Button_Click" />
<ContentControl ContentTemplate="{StaticResource contentTemplate}" />
<!--<m:UserControl1 />-->
</StackPanel>
</ContentControl>
</Grid>
In the user control paste the following code:
<UserControl.Resources>
<DataTemplate x:Key="contentTemplateInsideUserControl">
<TextBlock Name="textBlockInResourse" Text="textBlockInsideUserControlResource"
Style="{DynamicResource TextBlockStyleFontAndBackgound}"/>
</DataTemplate>
</UserControl.Resources>
<Grid>
<StackPanel>
<ContentControl ContentTemplate="{StaticResource contentTemplateInsideUserControl}" />
<Button Content="St" Click="Button_Click" />
<TextBlock Name="textBlockInControl" Text="textBlockInsideUserControl"
Style="{DynamicResource TextBlockStyleFontAndBackgound}" />
</StackPanel>
</Grid>
We have 2 text blocks with the same background color, blue, but with different font sizes.
textBlockInResourse FontSize = 20, taken from the style TextBlockStyleFontAndBackgound
textBlockInControl FontSize = 10, inherited value, why does it happen?
I have added a handle in the user control:
private void Button_Click(object sender, RoutedEventArgs e)
{
Style style = FindResource("TextBlockStyleFontAndBackgound") as Style;
textBlockInControl.Style = null;
textBlockInControl.Style = style;
}
And now the Font is set to the style TextBlockStyleFontAndBackgound, and it's size is 20
Why now the FontSize is taken from the style TextBlockStyleFontAndBackgound.
Thanks,
barak

That's a very peculiar problem you have found there. I'm not sure why the FontSize is not affected when not in a DataTemplate... looking at the two property descriptions and remarks on MSDN, the only difference between them is that TextBlock.FontSize is also an AttachedProperty, but I can't see how that would affect anything.
I can however offer a solution to the problem if you're still interested. Try declaring your Style in your App.xaml file:
<Application.Resources>
<Style TargetType="{x:Type TextBlock}" x:Key="TextBlockStyleFontAndBackgound">
<Setter Property="FontSize" Value="20" />
<Setter Property="Background" Value="Blue" />
</Style>
</Application.Resources>
Then declare your TextBlock in your UserControl using StaticResource like so:
<TextBlock Text="text" Style="{StaticResource TextBlockStyleFontAndBackgound}" />

Related

How to make WPF ComboBox items background Visible?

<Grid Grid.Row="5" Grid.Column="1">
<ComboBox Cursor="Hand" SelectedItem="{Binding SelectedRealEstate}" Background="White"
Name="cbbRealEstates" ItemsSource="{Binding RealEstateSummary}"/>
</Grid>
the code above gives me invisible item background
How do I make the background visible?
According to this,
You will have to set the styles in the resources of the element. In my case it's a window. So it's
<Window.Resources>
<Style x:Key="ComboBoxItemStyle" TargetType="ComboBoxItem">
<Setter Property="Background" Value="Blue" />
</Style>
<Style x:Key="ComboBoxStyle" TargetType="ComboBox">
<Setter Property="ItemContainerStyle" Value="{StaticResource ComboBoxItemStyle}" />
</Style>
</Window.Resources>
Set a style for ComboBoxItem. And use that style when you set the style for the ComboBox
Then apply the Combobox Style to the element.
<ComboBox Name="myCmb" Style="{StaticResource ComboBoxStyle}">

Mouseover border in a custom control for a textblock

I am trying to create a custom control for a text block that when moused over, a border will appear. I am pretty new to WPF and have only made some very simple custom controls. I need to implement this in a XAML UserControl.
Any suggestions would be greatly appreciated. Thanks again, StackOverflow.
EDIT: I am going to have to bind a persistence property to several different controls, so I really need to do this in a custom control. This is what I have, and it isn't working:
xmlns:customControls="clr-namespace:****.CustomControls"
....
<customControls:MouseOverBorder>
<TextBlock Style="{StaticResource ResourceKey=HomePageButtonText}"
Height="100"
Width="100"
Margin="5"
Text="View Reports" />
</customControls:MouseOverBorder>
And the UserControl:
<UserControl
x:Class="****.MouseOverBorder"
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">
<UserControl.Resources>
<ResourceDictionary>
<Style x:Key="MouseOverBorder" TargetType="{x:Type Border}">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="3" />
<Style.Triggers>
<Trigger Property="Border.IsMouseOver" Value="true">
<Setter Property="BorderBrush" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</UserControl.Resources>
<Border Style="{DynamicResource MouseOverBorder}" BorderThickness="1" CornerRadius="3" SnapsToDevicePixels="True"/>
No need to make a UserControl. I've managed to accomplish this with the following markup:
<Border Style="{DynamicResource BorderStyle1}" BorderThickness="1" CornerRadius="3" >
<TextBlock Text="TextBlock" />
</Border>
Here's the style:
<Style x:Key="BorderStyle1" TargetType="{x:Type Border}">
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="3"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="#FF123BBA"/>
</Trigger>
</Style.Triggers>
</Style>
EDIT:
Still don't get it why do you need a UserControl (please don't call it custom control - these are different things), but let's consider your example.
When you write the following
<customControls:MouseOverBorder>
<TextBlock Style="{StaticResource ResourceKey=HomePageButtonText}"
Height="100"
Width="100"
Margin="5"
Text="View Reports" />
</customControls:MouseOverBorder>
you are actually setting MouseOverBorder.Content property. Originally it's Content is defined in MouseOverBorder.xaml file. So you are replacing all your UserControl structure with TextBlock. But still I got your idea and have solution for it.
First, add custom DependencyProperty and CLR wrapper for it to MouseOverBorder class:
public static readonly DependencyProperty MyContentTemplateProperty =
DependencyProperty.Register("MyContentTemplate", typeof(DataTemplate), typeof(MouseOverBorder), null);
[Browsable(true)]
[Category("Other")]
public DataTemplate MyContentTemplate
{
get { return (DataTemplate)GetValue(MyContentTemplateProperty); }
set { SetValue(MyContentTemplateProperty, value); }
}
Second, make something inside MouseOverBorder use this property, e.g.
<ContentPresenter ContentTemplate="{Binding MyContentTemplate, ElementName=userControl}"/>
<!-- userControl is the Name of MouseOverBorder, defined in xaml -->
At last, you can use your UserControl as following:
<customControls:MouseOverBorder>
<customControls:MouseOverBorder.MyContentTemplate>
<DataTemplate>
<TextBlock Style="{StaticResource ResourceKey=HomePageButtonText}"
Height="100"
Width="100"
Margin="5"
Text="View Reports" />
</DataTemplate>
</customControls:MouseOverBorder.MyContentTemplate>
</customControls:MouseOverBorder>

WPF UserControl Style -- How do I set the style from the parent if the control is in an external assembly?

Basically I have the following structure:
<Window ...
xmlns:my="http://schemas.company.com/WPF/Controls"
>
<Window.Resources>
<Style x:Key="MyStyle1" TargetType={x:Type TextBlock}>
...
</Style>
</Window.Resources>
<Grid x:Name="LayoutRoot">
<my:MyUserControl1 />
<my:MyUserControl1 />
<my:MyUserControl2 />
<my:MyUserControl2 />
</Grid>
</Window>
<UserControl ...
>
<TextBlock Style={ ?? What Goes Here ??} />
</UserControl>
How do I apply the style declared in the Window resources so that it goes to the UserControl that is being pulled from an external assembly?
If you want the Style to be applied to all TextBlocks, including the ones in MyUserControl, just leave the x:Key out and it will be applied implictly
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Green"/>
</Style>
If you want it to be set explicitly you can use DynamicResource in the UserControls
<Window.Resources>
<Style x:Key="MyStyle1" TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Green"/>
</Style>
</Window.Resources>
<StackPanel>
<my:UserControl1 />
<my:UserControl1 />
<my:UserControl1 />
<my:UserControl1 />
</StackPanel>
<UserControl ...>
<TextBlock Style="{DynamicResource MyStyle1}" Text="TextBlock"/>
</UserControl>
Try this :
<TextBlock Style={ StaticResource MyStyle1} />
I hope this help you Introduction to Styles in WPF

Setting VerticalAlignment property to all controls

My WPF UserControl contains two stack panels and each of them contains labels, text boxes and radio buttons.
I would like to set VerticalAlignment property to Center to all controls in my UserControl with as little code as possible.
Now I have following solutions:
brute force - put VerticalAlignment="Center" in each control
define one style for FrameworkElement and apply it directly
define styles for each type of the controls on user control (this needs 3 style definitions, but automatically applies style to the control)
These three solutions need too much code.
Is there any other way to write this?
I hoped that defining style for FrameworkElement would automatically set property to all controls, but it does not work.
Here is snippet of my current XAML (I omitted second, very similar stack panel):
<UserControl.Resources>
<Style x:Key="BaseStyle" TargetType="FrameworkElement">
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</UserControl.Resources>
<Grid>
<StackPanel Orientation="Horizontal">
<TextBlock Style="{StaticResource BaseStyle}" Text="Value:" />
<RadioButton Style="{StaticResource BaseStyle}">Standard</RadioButton>
<RadioButton Style="{StaticResource BaseStyle}">Other</RadioButton>
<TextBox Style="{StaticResource BaseStyle}" Width="40"/>
</StackPanel>
</Grid>
Edit:
Re Will's comment: I really hate idea of writing control formatting code in codebehind. XAML should be sufficient for this really simple user control.
Re Muad'Dib's comment: Controls I use in my user control are derived from FrameworkElement, so this is not an issue here.
I had come across the same conundrum awhile ago as well. Not sure if this is the "best" way, but it was easy enough to manage by defining your base style and then creating separate styles for each control on the page that inherited from the base style:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="500" Height="300" Background="OrangeRed">
<Page.Resources>
<Style TargetType="FrameworkElement" x:Key="BaseStyle">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="0,0,5,0" />
</Style>
<Style TargetType="TextBlock" BasedOn="{StaticResource BaseStyle}" />
<Style TargetType="RadioButton" BasedOn="{StaticResource BaseStyle}" />
<Style TargetType="TextBox" BasedOn="{StaticResource BaseStyle}" />
</Page.Resources>
<Grid>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Value:" />
<RadioButton>Standard</RadioButton>
<RadioButton>Other</RadioButton>
<TextBox Width="75"/>
</StackPanel>
</Grid>
</Page>

How can I use a custom TabItem control when databinding a TabControl in WPF?

I have a custom control that is derived from TabItem, and I want to databind that custom TabItem to a stock TabControl. I would rather avoid creating a new TabControl just for this rare case.
This is what I have and I'm not having any luck getting the correct control to be loaded. In this case I want to use my ClosableTabItem control instead of the stock TabItem control.
<TabControl x:Name="tabCases" IsSynchronizedWithCurrentItem="True"
Controls:ClosableTabItem.TabClose="TabClosed" >
<TabControl.ItemTemplate>
<DataTemplate DataType="{x:Type Controls:ClosableTabItem}" >
<TextBlock Text="{Binding Path=Id}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate DataType="{x:Type Entities:Case}">
<CallLog:CaseReadOnlyDisplay DataContext="{Binding}" />
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
EDIT: This is what I ended up with, rather than trying to bind a custom control.
The "CloseCommand" im getting from a previous question.
<Style TargetType="{x:Type TabItem}" BasedOn="{StaticResource {x:Type TabItem}}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Border
Name="Border"
Background="LightGray"
BorderBrush="Black"
BorderThickness="1"
CornerRadius="25,0,0,0"
SnapsToDevicePixels="True">
<StackPanel Orientation="Horizontal">
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="20,1,5,1"/>
<Button
Command="{Binding Path=CloseCommand}"
Cursor="Hand"
DockPanel.Dock="Right"
Focusable="False"
Margin="1,1,5,1"
Background="Transparent"
BorderThickness="0">
<Image Source="/Russound.Windows;component/Resources/Delete.png" Height="10" />
</Button>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold" />
<Setter TargetName="Border" Property="Background" Value="LightBlue" />
<Setter TargetName="Border" Property="BorderThickness" Value="1,1,1,0" />
<Setter TargetName="Border" Property="BorderBrush" Value="DarkBlue" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
found a way,
derive a class from TabControl and override this function, in my case I want the items of the tab control (when bound) to be CloseableTabItems
public class CloseableTabControl : TabControl
{
protected override DependencyObject GetContainerForItemOverride()
{
return new CloseableTabItem();
}
}
HTH Someone
Sam
You don't want to set the DataType of the DataTemplate in this case. The value of the ItemTemplate property is used whenever a new item needs to be added, and in the case of a tab control it will be used to create a new TabItem. You should declare an instance of your class within the DataTemplate itself:
<TabControl x:Name="tabCases" IsSynchronizedWithCurrentItem="True" Controls:ClosableTabItem.TabClose="TabClosed">
<TabControl.ItemTemplate>
<DataTemplate>
<Controls:ClosableTabItem>
<TextBlock Text="{Binding Path=Id}" />
</Controls:ClosableTabItem>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate DataType="{x:Type Entities:Case}">
<CallLog:CaseReadOnlyDisplay DataContext="{Binding}" />
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
This will cause a new ClosableTabItem to be created whenever a new tab is added to the TabControl.
Update; From your comment, it sounds like that the ItemTemplate controls what is created within the TabItem, rather than changing the TabItem itself. To do what you want to do, but for a TreeView, you would set the HeaderTemplate. Unfortunately, I don't see a HeaderTemplate property of TabControl.
I did some searching, and this tutorial modifies the contents of the tab headers by adding controls to TabItem.Header. Maybe you could create a Style for your TabItems that would add the close button that your class is currently adding?

Resources