Setting the Header of GroupBox in a GroupBox style - c#

I'm getting XAML parse exceptions when using a certain GroupBox Style more than once. I'm keeping the style in UserControl.Resources.
Here is an example of a simplified style that does not cause a XAML parse exception:
<Style x:Key="MyGroupBoxStyle" TargetType="GroupBox" BasedOn="{StaticResource {x:Type GroupBox}}">
<Setter Property="BorderThickness" Value="5" />
<Setter Property="Header" Value="Hello World!" />
</Style>
Here is another one that does not cause a problem.
<Style x:Key="MyGroupBoxStyle" TargetType="GroupBox" BasedOn="{StaticResource {x:Type GroupBox}}">
<Setter Property="BorderThickness" Value="5" />
<Setter Property="Header">
<Setter.Value>
Hello World!
</Setter.Value>
</Setter>
</Style>
This one however does cause a problem:
<Style x:Key="MyGroupBoxStyle" TargetType="GroupBox" BasedOn="{StaticResource {x:Type GroupBox}}">
<Setter Property="BorderThickness" Value="5" />
<Setter Property="Header">
<Setter.Value>
<TextBlock Text="Hello World!" />
</Setter.Value>
</Setter>
</Style>
Again, it's only a problem when I use the style on more than one GroupBox. If I use it just once, I don't get the XAML parse exception. And it doesn't have to be just a TextBlock. I think it's any UIElement.
Any ideas? Thanks!

You cannot set the content of the header to another UI control in the style. Try creating a datatemplate.
<Window.Resources>
<Style x:Key="MyGroupBoxStyle" TargetType="GroupBox" BasedOn="{StaticResource {x:Type GroupBox}}">
<Setter Property="BorderThickness" Value="5" />
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="Hello World!!!!!!"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel>
<GroupBox Style="{StaticResource MyGroupBoxStyle}" Height="200" Width="200"/>
<GroupBox Style="{StaticResource MyGroupBoxStyle}" Height="200" Width="200"/>
</StackPanel>

Related

WPF - Font Awesome icons not showing in runtime

I'm building WPF application and I want to use icons from Font Awesome. I have Font Awesome included in styles, and a font family specified in fields where I want to use it. The problem is icons are showing properly in the design window but change to crossed squares during runtime.
There is my Fonts XAML
<FontFamily x:Key="ArconRegular">pack://application;,,,/Fonts/#Arcon</FontFamily>
<FontFamily x:Key="ArconRounded">pack://application;,,,/Fonts/#Arcon Rounded-</FontFamily>
<FontFamily x:Key="FASolid">pack://application;,,,/Fonts/#Font Awesome 5 Free Solid</FontFamily>
<Style TargetType="{x:Type Control}" x:Key="BaseStyle">
<Setter Property="FontFamily" Value="{StaticResource ArconRegular}"/>
</Style>
<Style TargetType="{x:Type TextBlock}" x:Key="BaseTextBlockStyle">
<Setter Property="FontFamily" Value="{StaticResource ArconRegular}"/>
</Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource BaseStyle}"/>
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource BaseStyle}"/>
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource BaseStyle}"/>
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource BaseTextBlockStyle}"/>
<Style TargetType="{x:Type ListView}" BasedOn="{StaticResource BaseStyle}"/>
<system:String x:Key="FAMinimizeIcon"></system:String>
<system:String x:Key="FAMaximizeIcon"></system:String>
<system:String x:Key="FACloseIcon"></system:String>
The Buttons XAML (I want to use icons on buttons)
<Style TargetType="{x:Type Button}" x:Key="WindowControlButton" BasedOn="{StaticResource BaseStyle}">
<Setter Property="FontFamily" Value="{StaticResource FASolid}"/>
<Setter Property="WindowChrome.IsHitTestVisibleInChrome" Value="True"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Padding" Value="3"/>
<Setter Property="Foreground" Value="{StaticResource ForegroundMainBrush}"/>
<Setter Property="LayoutTransform">
<Setter.Value>
<ScaleTransform ScaleX="1.5"/>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Padding="{TemplateBinding Padding}" Background="{TemplateBinding Background}">
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Text="{TemplateBinding Content}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource BackgroundLightBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
And finally MainWindow XAML (a part of it where i want to use them)
<!-- Window Buttons -->
<StackPanel Grid.Column="2" Orientation="Horizontal">
<Button Style="{StaticResource WindowControlButton}" Content="{StaticResource FAMinimizeIcon}" Command="{Binding MinimizeCommand}"/>
<Button Style="{StaticResource WindowControlButton}" Content="" Command="{Binding MaximizeCommand}"/>
<Button Style="{StaticResource WindowCloseButton}" Content="" Command="{Binding CloseCommand}"/>
</StackPanel>
As you can see, I tried specifying icon code in separate string and using StaticResource but nothing works.
In my case it was missing FontFamily="{TemplateBinding FontFamily}" in the ControlTemplate
Had a same issue, i.e Showing ok in Design mode but no Runtime. For me it was because fontawesome was not included in the assembly.
Changed (in visual studio) the .otf file's Build Action to "Resource". You may want to check if the file is included in your assembly by decompiler.

How to set one content to several buttons in WPF

I have some buttons -in different windows- that have the same content. But if two windows surfaced together,out of the first window's button content disappears.
Buttons Style is :
<Style TargetType="{x:Type Button}" x:Key="BSaveBtn">
<Setter Property="Padding" Value="5"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Width" Value="70"/>
<Setter Property="Height" Value="68"/>
<Setter Property="Background" Value="{DynamicResource FlatGreen}"/>
<Setter Property="Template" Value="{DynamicResource FlatGreenBtnHover}"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="Content">
<Setter.Value>
<StackPanel Orientation="Vertical" FlowDirection="RightToLeft">
<Image Width="30" Source="/login;component/img/buttonpic/save.png"/>
<TextBlock Text="save" FontSize="16" FontFamily="/login;component/fonts/#Droid Arabic Kufi" Foreground="White" HorizontalAlignment="Center"/>
</StackPanel>
</Setter.Value>
</Setter>
</Style>
button Code in windows is :
<Button Style="{DynamicResource BSaveBtn}" Template="{DynamicResource FlatGreenBtnHover}" />
problems occurs only with content -not another style properties- .
Seems to work fine for me when I tested it here.
A few things I noticed though that may help. You don't need them to be DynamicResource, they should really be StaticResource unless you plan on modifying them.
I assume you are declaring these in the Windows.Resource section or repeating them on each window?
If so you should centralize those to a ResourceDictionary.
Create a new Resource Dictionary put your style in there like so:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="{x:Type Button}" x:Key="BSaveBtn">
<Setter Property="Padding" Value="5"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Width" Value="70"/>
<Setter Property="Height" Value="68"/>
<Setter Property="Background" Value="{DynamicResource FlatGreen}"/>
<Setter Property="Template" Value="{DynamicResource FlatGreenBtnHover}"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="Content">
<Setter.Value>
<StackPanel Orientation="Vertical" FlowDirection="RightToLeft">
<Image Width="30" Source="/login;component/img/buttonpic/save.png"/>
<TextBlock Text="save" FontSize="16" FontFamily="/login;component/fonts/#Droid Arabic Kufi" Foreground="White" HorizontalAlignment="Center"/>
</StackPanel>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Then in your App.xaml put the following:
<ResourceDictionary>
<ResourceDictionary Source="MyResources.xaml" />
</ResourceDictionary>
The Image should really be in a dictionary to avoid loading it multiple times. Just add a line in that ResourceDictionary like so:
<BitmapImage UriSource="/login;component/Images/Save.png" x:Key="Save" PresentationOptions:Freeze="True" />
Setting the PresentationOptions:Freeze will also help if the image is never being modified.
Your call to the image would then change to be:
<StackPanel Orientation="Vertical" FlowDirection="RightToLeft">
<Image Width="30" Source="{StaticResource Save}"/>
<TextBlock Text="save" FontSize="16" FontFamily="/login;component/fonts/#Droid Arabic Kufi" Foreground="White" HorizontalAlignment="Center"/>
</StackPanel>
Once your resources are centralized in a ResourceDictionary (or multiple) it makes it easy to apply those same styles anywhere in your application and hopefully will help with your issue. If not please give more info on the problem you have such as sample code to make the issue happen please.
An instance of an element can only appear once in the visual tree. You can set the x:Shared attribute of the Style to False in order for a new instance of the StackPanel to get created for each Button to which you apply the style:
<Style TargetType="{x:Type Button}" x:Key="BSaveBtn" x:Shared="False">
<Setter Property="Padding" Value="5"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Width" Value="70"/>
<Setter Property="Height" Value="68"/>
<Setter Property="Background" Value="{DynamicResource FlatGreen}"/>
<Setter Property="Template" Value="{DynamicResource FlatGreenBtnHover}"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="Content">
<Setter.Value>
<StackPanel Orientation="Vertical" FlowDirection="RightToLeft">
<Image Width="30" Source="/login;component/img/buttonpic/save.png"/>
<TextBlock Text="save" FontSize="16" FontFamily="/login;component/fonts/#Droid Arabic Kufi" Foreground="White" HorizontalAlignment="Center"/>
</StackPanel>
</Setter.Value>
</Setter>
</Style>

wpf create style for named element

Is it possible to add style to xaml element without editing the element?
for example:
xaml element:
<Grid>
<Grid x:Name="A">content A</Grid>
<Grid x:Name="B">content B</Grid>
</Grid>
and style:
<Style x:Key="StyleForA" TargetName="A" TargetType="{x:Type Grid}" >
<Setter Property="Background" Value="Red"/>
</Style>
<Style x:Key="StyleForB" TargetName="B" TargetType="{x:Type Grid}" >
<Setter Property="Background" Value="Green"/>
</Style>
UPD:
I have a project with a lot of styles (aero, black, etc ).
And if I edit the element Style="{StaticResources StyleForA}" I must edit all styles.
So I need to create local style that affected to named element.
Natively you can't.
But without touching your XAML, you can do it very easily using code :
Grd1.Style = (Style) this.Resources["GridKey"];
Pure XAML approach using Blend behaviors,
<Grid x:Name="Grd1">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<ic:ChangePropertyAction PropertyName="Style" Value="{DynamicResource GridKey}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Grid>
Yes. I use this style on my App.xaml to add a teplate around all aplication controls with error:
<Style x:Key="BordaTemplate" TargetType="Control">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="True">
<Border BorderBrush="Red" BorderThickness="1">
<AdornedElementPlaceholder Name="myControl"/>
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={x:Static RelativeSource.Self},
Path=(Validation.Errors).CurrentItem.ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="TextBox" BasedOn="{StaticResource BordaTemplate}" />
<Style TargetType="PasswordBox" BasedOn="{StaticResource BordaTemplate}" />
<Style TargetType="DataGrid" BasedOn="{StaticResource BordaTemplate}" />
<Style TargetType="ListBox" BasedOn="{StaticResource BordaTemplate}" />
<Style TargetType="CheckBox" BasedOn="{StaticResource BordaTemplate}" />
<Style TargetType="ComboBox" BasedOn="{StaticResource BordaTemplate}" />
<Style TargetType="DatePicker" BasedOn="{StaticResource BordaTemplate}" />
Not like as you have defined using target but if you want to apply a style to a specific control. then use below:
<StackPanel>
<Button x:Name="A">
<Button.Resources>
<Style TargetType="{x:Type Button}" >
<Setter Property="Background" Value="Red"/>
</Style>
</Button.Resources>
content A</Button>
<Button x:Name="B">
<Button.Resources>
<Style TargetType="{x:Type Button}" >
<Setter Property="Background" Value="Green"/>
</Style>
</Button.Resources>
content B</Button>
</StackPanel>
Or probably create a base style and then create a BasedOn style for your controls.
Update: If you only want to be concerned about the style at a time and be sure of impacted elements:
<Window.Resources>
<Style TargetType="{x:Type Button}" x:Key="First" >
<Setter Property="Background" Value="Red"/>
</Style>
<Style TargetType="{x:Type Button}" x:Key="Second" >
<Setter Property="Background" Value="Green"/>
</Style>
</Window.Resources>
<StackPanel>
<Button x:Name="A">
<Button.Resources>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource First}" />
</Button.Resources>
content A</Button>
<Button x:Name="B">
<Button.Resources>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource Second}" />
</Button.Resources>
content B</Button>
</StackPanel>
I think you can have a default style and you can override the properties you want on your local style.
<Grid>
<Grid.Resources>
<Style TargetType="Button" x:Key="Default">
<Setter Property="Background" Value="White"></Setter>
<Setter Property="Foreground" Value="Blue"/>
</Style>
<Style x:Key="StyleForA" BasedOn="{StaticResource Default}" TargetType="Button" >
<Setter Property="Background" Value="Red" ></Setter>
</Style>
<Style x:Key="StyleForB" BasedOn="{StaticResource Default}" TargetType="Button" >
<Setter Property="Background" Value="Green" ></Setter>
</Style>
</Grid.Resources>
<StackPanel>
<Button Style="{StaticResource StyleForA}" Width="100" x:Name="A" Click="Button_Click" Height="100">Test A</Button>
<Button Style="{StaticResource StyleForB}" Width="100" x:Name="B" Click="Button_Click" Height="100">Test B</Button>
</StackPanel>
</Grid>

Customize Microsoft.Phone.Controls.Rating

I need to customize the Microsoft.Phone.Controls.Rating control. Below code creates a template a bit closer but i need to change icons.
<Style x:Key="RatingStyle" TargetType="toolkit:Rating">
<Setter Property="AllowHalfItemIncrement" Value="True" />
<Setter Property="Width" Value="100" />
<Setter Property="Height" Value="20" />
<Setter Property="FilledItemStyle">
<Setter.Value>
<Style TargetType="toolkit:RatingItem">
<Setter Property="Background"
Value="#FF9900" />
</Style>
</Setter.Value>
</Setter>
<Setter Property="UnfilledItemStyle">
<Setter.Value>
<Style TargetType="toolkit:RatingItem">
<Setter Property="Background"
Value="#E0E0E0" />
</Style>
</Setter.Value>
</Setter>
</Style>
My required templates are 2, 1 for place rating and one for average price level (shown by $ sign). below is the image showing my requirement.
I find the quickest method is to change the Template of the two styles to adjust the image/look:
<Style x:Name="UnfilledDollarStyle" TargetType="toolkit:RatingItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="toolkit:RatingItem">
<Border HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock FontSize="30" Foreground="Silver">$</TextBlock>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Name="FilledDollarStyle" TargetType="toolkit:RatingItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="toolkit:RatingItem">
<Border HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock FontSize="30" Foreground="Green">$</TextBlock>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
In use:
<toolkit:Rating UnfilledItemStyle="{StaticResource UnfilledDollarStyle}"
FilledItemStyle="{StaticResource FilledDollarStyle}" Value="2" />
By editing the Template, you could use images or whatever you'd like within each RatingItem.
Of course, you could leave the unfilled style "empty" or completely transparent so that no symbols are shown at all. (To keep consistent spacing around the control, I'd suggest using a fully transparent symbol rather than no content). Here, I've set the Opacity to 0:
<TextBlock FontSize="30" Opacity="0">$</TextBlock>

Apply Style to all child-elements of specific type

I want to write a style for wpf where all buttons in a StatusBar (that has a defined style) have the same style (e.g. width).
Here is what my style looks like:
<Style TargetType="{x:Type StatusBar}"
x:Key="DialogBoxStatusBarStyle">
<Setter Property="Background"
Value="LightGray" />
<Setter Property="Padding"
Value="5" />
...?
</Style>
And the xaml for the elements:
<StatusBar Style="{StaticResource ResourceKey=DialogBoxStatusBarStyle}" Grid.Row="3"
FlowDirection="RightToLeft">
<Button Content="Übernehmen"
Width="100"
HorizontalAlignment="Right" />
<Button Content="Abbrechen"
Width="100"
HorizontalAlignment="Right" />
<Button Content="OK"
Width="100"
HorizontalAlignment="Right" />
</StatusBar>
In the final version I don't want to set width to 100 for all buttons. This should be defined in the style of the StatusBar or better say in the style of the button-childs of the StatusBar.
You could add a default Style for Buttons to the Resources of your DialogBoxStatusBarStyle:
<Style TargetType="StatusBar" x:Key="DialogBoxStatusBarStyle">
<Style.Resources>
<Style TargetType="Button">
<Setter Property="Width" Value="100"/>
</Style>
</Style.Resources>
...
</Style>
To extend on the answer above (#Clemens), you could even do something like this, to reuse a button style independently, and also apply it to children of a specific container.
Styles:
<Style TargetType="{x:Type Button}" x:Key="MyButtonStyle">
<Setter Property="Width" Value="100" />
<Setter Property="HorizontalAlignment" Value="Right" />
</Style>
<Style TargetType="{x:Type StatusBar}" x:Key="DialogBoxStatusBarStyle">
<Setter Property="Background" Value="LightGray" />
<Setter Property="Padding" Value="5" />
<Style.Resources>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource MyButtonStyle}" />
</Style.Resources>
...
</Style>

Categories

Resources