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.
Related
I have created a ResourceDictionary style sheet that have a style named btn_default.
I plan to use it on all the buttons in my program. My problem is that when I hover the button then the background-color doesnt change. The font color changes.
button_default
button_default:hover
I tried in my code to change the "Setter Property="Background" Value="#b5b5b5"", however I guess that doesnt affect the Border-tag, but the Style-tag?
ResourceDictionary
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MSDNSample">
<!-- Btn default -->
<Style x:Key="btn_default" TargetType="{x:Type Button}">
<Setter Property="FontFamily" Value="Calibri"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Foreground" Value="#d9d9d9" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="5" BorderThickness="1" Padding="6,4,6,4" Background="#6c6c6c" BorderBrush="#393939">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#b5b5b5"/>
<Setter Property="Foreground" Value="#000000" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- //Btn default -->
</ResourceDictionary>
Main
<Button x:Name="buttonExplorer" Content="Explorer" Style="{StaticResource btn_default}" Margin="0,0,6,0" />
<Button x:Name="buttonProcess" Content="Process" Style="{StaticResource btn_default}" Margin="0,0,6,0" />
You should declare Background property of Border using TemplateBinding extension and set Background value in Style setter, otherwise it'll never be updated
<Style x:Key="btn_default" TargetType="{x:Type Button}">
<Setter Property="FontFamily" Value="Calibri"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Foreground" Value="#d9d9d9" />
<Setter Property="Background" Value="#6c6c6c"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="5" BorderThickness="1" Padding="6,4,6,4" BorderBrush="#393939" Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#b5b5b5"/>
<Setter Property="Foreground" Value="#000000" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I've got about 300+ buttons that are represented in a grid. When I try to render this, it takes a good 5 seconds to load up all buttons. Is there any alternative? Functionality that already exists such as hover over, mouse enter, left button click etc are all needed... just wondering if there is a way to speed up button rendering.
Buttons are created dynamically in a grid, with an ItemsControl, that contains an ItemsPanelTemplate (that is just a grid definition of width and height), a DataTemplate in ItemsControl.Resources, where the ToggleButton(s) that are created dynamically (300+) are created.
The datatemplate in the ItemsControl.Resources looks like this:
<DataTemplate DataType="{x:Type engine:Weodel}">
<ToggleButton
Tag="{Binding}"
IsChecked="{Binding IsSelected}"
Height="{Binding ElementName=weItemControl,
Path=DataContext.ButtonHeightWidth}"
Width="{Binding ElementName=weItemControl,
Path=DataContext.ButtonHeightWidth}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Margin="{Binding ElementName=weItemControl,
Path=DataContext.ButtonMarginToUse}"
Padding="2"
Style="{StaticResource WeButton}">
</ToggleButton>
</DataTemplate>
The style of the button in resource dictionary:
<Style TargetType="{x:Type ToggleButton}" x:Key="WeButton">
<Setter Property="Background" Value="White"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid>
<Ellipse Fill="{TemplateBinding Background}" />
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" TextBlock.TextAlignment="Center">
<ContentPresenter.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="TextAlignment" Value="Center"/>
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Background" Value="{Binding GColour}"/>
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Background" Value="{Binding GColour}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I'm trying to learn how to make a custom control. I've been searching all afternoon, but can't get my properties to be used by the child controls.
For example my TextBox subclass is TextBoxCalculator. In the control template I have a textbox and a popup.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Controls">
<Style TargetType="local:TextBoxCalculator" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:TextBoxCalculator">
<Grid Name="ucGrid">
<TextBox Name="AmountTb" Text="{Binding Text }">
<!--<TextBox.Style>
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
... How can I make this textbox style follow the one specified in the window XAML?
</Style>
</TextBox.Style>-->
</TextBox>
<Popup Name="calPopup" Placement="Top" StaysOpen="False">
... some content
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
In my window I use the control like this:
<Style TargetType="{x:Type controls1:TextBoxCalculator}" x:Key="RightCellEditCalc">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="TextAlignment" Value="Right"/>
<Setter Property="Background" Value="Red"/>
<Setter Property="BorderThickness" Value="0"/>
</Style>
<controls1:TextBoxCalculator Text="{Binding Amount, UpdateSourceTrigger=LostFocus}"
DecimalPlaces="2"
AutoPlaceDecimalPoint="True"
Style="{StaticResource RightCellEditCalc}"
Background="Green">
</controls1:TextBoxCalculator>
I would expect the background to be green, but it is white instead.
An the other hand the TextAlignment = Right seems to be working. What am I missing?
It makes no sense to define a TextBox element in the ControlTemplate of another custom TextBox control.
If you want to create a custom template for your control and base it on the default template of the TextBox control, you could right-click on a TextBox element in design mode in Visual Studio or in Blend and choose Edit Template->Edit a Copy to copy the default template into your XAML markup and then edit it as per your requirements.
This is how it looks like on Windows 8 and later:
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" TargetName="border" Value="0.56"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="#FF7EB4EA"/>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="#FF569DE5"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
It uses TemplateBindings to bind properties of the Border element in the template to the corresponding property of the TextBox control itself.
You are not binding the background.binding it at the place you want inside your ControlTemplate.For example
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Controls">
<Style TargetType="local:TextBoxCalculator" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:TextBoxCalculator">
<Grid Name="ucGrid">
<TextBox Name="AmountTb" Text="{Binding Text }" Background="{TemplateBinding Background}">
<!--<TextBox.Style>
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
... How can I make this textbox style follow the one specified in the window XAML?
</Style>
</TextBox.Style>-->
</TextBox>
<Popup Name="calPopup" Placement="Top" StaysOpen="False">
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
you can use the background now.
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>
I created a ressourceDictionnary for creating a templateButton.
I would like to be able to change the png image when i use this template, i think i need to use a ContentPresenter, but i don't know why.
Here is my RessourceDictionnary :
<ControlTemplate TargetType="{x:Type Button}" x:Key="BoutonRessources">
<Button Width="32" Margin="0,0,7,0" Name="tbrClear" ToolTip="Clear" VerticalAlignment="Center" BorderThickness="0" HorizontalAlignment="Center" Background="Transparent" HorizontalContentAlignment="Center">
<Border>
<Image Source="xRtDiva_XWPF_TBR_PREMIER.PNG_IMAGES.png" Height="18"/>
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="Background" Value="Transparent" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="BoutonToolbarSelected.png"/>
</Setter.Value>
</Setter>
<Setter Property="Height" Value="22"/>
<Setter Property="Width" Value="32"/>
</Trigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
</Button>
So, when i use this Button template, i would like to be able to pass them an other png image to display. For example i would like to replace xRtDiva_XWPF_TBR_PREMIER.PNG_IMAGES.png by MyPicture.png.
How doing this ? With a contentPresenter ?
Thanks :)