I have a question regarding styles in xaml wpf.
I have a Default style which should apply for all Objects. But for some of them I want to set a second style overriding a few attributes.
Now if I give my second style a x:key="style2" and set this as style, my first Default style is not applied, but the Default WPF style is. I can not/want not Change anything at my first Default style
How can I fix this behaivor?
To ensure that your default style is still applied, you add
BasedOn={StaticResource ResourceKey={x:Type ControlType}}
Where ControlType is the type of object the default style was applied to.
Here's an example:
<Window x:Class="StyleOverrides.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="FontFamily" Value="Comic Sans MS" />
</Style>
<Style x:Key="Specialization"
TargetType="{x:Type TextBlock}"
BasedOn="{StaticResource ResourceKey={x:Type TextBlock}}"
>
<Setter Property="FontStyle" Value="Italic" />
<Setter Property="Foreground" Value="Blue" />
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Viewbox Grid.Row="0" >
<TextBlock>This uses the default style</TextBlock></Viewbox>
<Viewbox Grid.Row="1">
<TextBlock Style="{StaticResource Specialization}">
This is the specialization
</TextBlock>
</Viewbox>
</Grid>
</Window>
Related
It is stated in MSDN that
Starting with Windows 10, version 1809, you can use the x:Bind markup extension anywhere you use TemplateBinding in a ControlTemplate.
However, when I try to replace TemplateBinding with {x:Bind} whilst defining the style of a custom control, as so,
<Style TargetType="local:PomodoroTimer" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:PomodoroTimer">
<Grid Width="300" Height="300" Background="{x:Bind Background}">
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I get the following error: Unable to resolve symbol 'Background'. What am I missing?
x:Bind needs code-behind. (see here)
So, thanks to MainWindow.xaml.cs, this works:
<Window
x:Class="Bindings.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:local="using:Bindings"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid>
<Grid.Resources>
<Style
x:Key="CustomButtonStyle"
TargetType="Button">
<Style.Setters>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border
BorderBrush="{x:Bind BorderBrush, Mode=OneWay}"
BorderThickness="{x:Bind BorderThickness, Mode=OneWay}">
<ContentControl Content="{x:Bind Content, Mode=OneWay}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
</Grid.Resources>
<Button
BorderBrush="SkyBlue"
BorderThickness="1"
Content="Custom Button"
Style="{StaticResource CustomButtonStyle}" />
</Grid>
</Window>
For custom (templated) controls, I'd go with:
Text="{TemplateBinding Text}"
or
Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
for TwoWay bindings.
If you want to do x:Bind inside the ControlTemplate, this answer might help.
Custom Control.cs
public class CustomButtons: Control
{
public static readonly DependencyProperty CmdExecProperty = DependencyProperty.Register(nameof(CmdExec), typeof(bool), typeof(CustomButtons), new PropertyMetadata("True"));
public bool CmdExec
{
get => (bool)GetValue(CmdExecProperty);
set => SetValue(CmdExecProperty, value);
}
Generic.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:v="clr-namespace:ServicePageKit"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
mc:Ignorable="d">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Theme/CompoundControlStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
<!-- Control template for a CustomButtons -->
<ControlTemplate x:Key="CustomButtonsTemplate"
TargetType="{x:Type v:CustomButtons}">
<Grid Width="128"
d:DesignHeight="200">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition MaxHeight="52" />
</Grid.RowDefinitions>
<Button x:Name="LoadButton"
Grid.Row="1"
Height="50"
HorizontalAlignment="Stretch"
Command="{Binding CopyCommand}"
CommandParameter="{Binding Path=Critical,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type v:CustomButtons}},
Mode=OneWay}"
Content="Copy"
IsEnabled="true" />
</Button>
</Grid>
</ControlTemplate>
<Style x:Key="CustomButtonsStyle"
TargetType="{x:Type v:CustomButtons}">
<Setter Property="Template" Value="{StaticResource CustomButtonsTemplate}" />
</Style>
<Style TargetType="{x:Type v:CustomButtons}" BasedOn="{StaticResource CustomButtonsStyle}" />
</ResourceDictionary>
Usage
<kit:CustomButtons x:Name="SyskonButtons"
CmdExec="True"/>
This CustomControl works fine but I want that when CmdExec DepenpencyProperty is True, then the command (command names is used in Generic.xaml under Button) should execute, regardless the button is pressed or not.
I'm doing a WPF program, with some textbox, labels and buttons.
Using the XAML designer, it works fine, the components are shown as they should. But when I run the program, it seems that the window shortens and cut some components in the sides.
Why are the components (button and labbel) being cut only when I run the program?
Here's the Xaml code of the 2 affected components:
<Window x:Class="XML_Edit.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:XML_Edit"
mc:Ignorable="d"
Title="XML_Edit" Height="380" Width="470" ResizeMode="NoResize" Icon="Imagenes/xml.png">
<Window.Resources>
<Style TargetType="{x:Type Button}">
<Style.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="4" />
</Style>
</Style.Resources>
</Style>
<Style TargetType="{x:Type TextBox}">
<Style.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="4" />
</Style>
</Style.Resources>
</Style>
</Window.Resources>
<Grid Background="#FF363944">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="49*"/>
<ColumnDefinition Width="183*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="15"/>
<RowDefinition Height="80"/>
<RowDefinition Height="80"/>
<RowDefinition Height="45"/>
<RowDefinition Height="50*"/>
</Grid.RowDefinitions>
<!-- Components -->
<Button Name="btCambiarContenido" Grid.Row="4" Content="Cambiar Contenido" VerticalAlignment="Center" HorizontalAlignment="Left" VerticalContentAlignment="Center" Margin="26,80,0,16" Height="36" Width="135" Click="BtCambiarContenido_Click" TabIndex="5" Background="{x:Null}" BorderBrush="#FF4EB8CE" FontSize="14" Grid.ColumnSpan="2" Foreground="#FF4EB8CE"/>
<Label Name="lbSeleccionarRuta" Grid.Row="1" ToolTip="Seleccionar archivo" Height="32" Width="32" Margin="293.333,32,41,16" MouseDown="LbSeleccionarRuta_MouseDown" Grid.Column="1">
<Label.Style>
<Style TargetType="Label">
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="Imagenes/folder_azul.png"/>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="Imagenes/folder_gris.png"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
</Grid>
They are shown fine in the WPF editor:
But they fet cut when I run the program:
You're setting your Button height to 36 pixels and giving it a margin of 26,80,0,16. This is effectively telling the layout manager that you want 36+80+16=132 pixels reserved to accommodate that button in row 4.
Meanwhile, in your grid layout you're specifying the rows 0-3 to have 15+80+80+45 pixels reserved. Combined with the 132 you're reserving for your button that's 352. But you're also explicitly setting your window height to 380, and that has to accommodate not just your 352 client area pixels but also the border and caption (as an experiment set your WindowStyle to None to remove the border and caption bar and you'll see your full control appear again). The layout manager has to cut pixels somewhere, and since row 4 is the only one you've specified with a "*" that's where they get cut, so the top and bottom of your button get cut as well. The reason you're not seeing this in designer is because it's using different theming to your OS, which is taking into account things like screen DPI, Windows theme settings, accessibility and several other things; the caption bar in designer is simply a bit smaller.
Issues like this are one of the many reasons you have to be careful doing explicit pixel layouts in WPF, and why you have to be especially careful with margins.
I can apply a background image to a StackPanel with this XAML code:
<StackPanel>
<StackPanel.Background>
<ImageBrush ImageSource="bg.png" Stretch="Uniform" AlignmentY="Bottom" />
</StackPanel.Background>
...
</StackPanel>
But that's kind of a lot to type when applied to multiple StackPanels. So I'd rather define a Style (aka Static Resource?) that I can quickly apply to the individual StackPanels.
So I started writing this:
<Window.Resources>
<ImageBrush x:Key="SpBg" ImageSource="bg.png" Stretch="Uniform" AlignmentY="Bottom" />
<Style x:Key="StackPanelBg" TargetType="StackPanel">
<!-- begin invalid xaml -->
<Setter Property="Background" Value="SpBg" />
<!-- end invalid xaml -->
</Style>
</Window.Resources>
So that I'd be able to do this:
<StackPanel Style="{StaticResource StackPanelBg}">
...
</StackPanel>
Except that doesn't work; the Setter line isn't correct. How can I make this work?
Like that:
<Window x:Class="WpfApplication12.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ImageBrush x:Key="SpBg" ImageSource="bg.png" Stretch="Uniform" AlignmentY="Bottom" />
<Style x:Key="StackPanelBg" TargetType="StackPanel">
<Setter Property="Background" Value="{StaticResource SpBg}" />
</Style>
</Window.Resources>
<StackPanel Style="{StaticResource StackPanelBg}">
</StackPanel>
</Window>
I created <Style TargetType="Label"> I am using it on all labels.
But there is one label that I don't want to use this Style there I just want to stay default .
Any way to do so?
<Label Style="{x:Null}" />
should do the trick
Don't think there is something like a DoNotApplyStyle Boolean on a UIElement. What you can do is simply give that special label it's own unique style which mimics the default style.
<Label Text="Special label">
<Label.Style>
<Style>
<Setter Property="FontSize" Value="11"/>
...
</Style>
</Label.Style>
</Label>
Just create a named style for the one you don't want to have the implicit style, and assign it to it.
for example:
<Window x:Class="WpfApplication6.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" x:Name="MyWindow">
<Window.Resources>
<Style TargetType="Label">
<Setter Property="Foreground" Value="Red"/>
</Style>
<Style x:Key="DefaultStyle" TargetType="Label"/>
</Window.Resources>
<StackPanel x:Name="MainCanvas">
<Label>Sample 1</Label>
<Label Style="{StaticResource DefaultStyle}">Sample 2</Label>
<Label>Sample 3</Label>
</StackPanel>
</Window>
in this example all labels will have red foreground except the ones you assign the DefaultStyle will have a default style (foreground black)