Design responding Triggers, defining and using WPF - c#

Recently I read about styles and control templates. As it says control templates are responsible for whole control design. But, I want for example to change only SPECIFIC part of the default control template, for example when mouse is over, or control has focus, when I wrote this:
<Style x:Key="StyleTextBox" TargetType="TextBox">
<Setter Property="Margin" Value="5, 0"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="SelectionBrush" Value="#CCFBE6D9"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="Black" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
..whole template got overridden... and its kinda not cool...
So how to change only isMouseOver visual style, without overriding the whole default style?

The whole template got replaced because your XAML says, "set the Template to this ControlTemplate that I'm declaring right here." Problem is, your template is empty. Use a template when you want to tell WPF, "represent the control using this visual tree". You gave it an empty visual tree and got exactly what you asked for ;).
In this case, however, your intention isn't to change the visual structure of the control; you just want to change a property. You can still use a Trigger and Setter for this, but you need not create a template to do so. A Style has its own collection of triggers, so you can just move it there:
<Style x:Key="StyleTextBox" TargetType="TextBox">
<Setter Property="Margin" Value="5, 0"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="SelectionBrush" Value="#CCFBE6D9"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="Black" />
</Trigger>
</Style.Triggers>
</Style>
This works because you're just changing a property of the styled control; generally, you can expect templates to honor the top-level properties of the controls to which the template is applied. For example, the default TextBox template should ensure that the TextBox is drawn with a background conforming to the templated parent's Background property.
Triggers on templates are more useful in cases where you want to manipulate a specific sub-element declared within a custom template.

Related

Styling a Button with MenuItems WPF

Please i need a way to come up with a style like these
But this is the current one i'm using
Please if you can help out with maybe a Link, Code, Tutorial on how to get it done, i'll greatly appreciate. Thanks..
Modifying the styles of a MenuItem (WPF) is more complicated than it might seem, because the same MenuItem control uses different templates depending on the Role assigned to each MenuItem: SubmenuItem, TopLevelHeader and SubmenuHeader.
With the menu bar you should not have any problem: if you want, you can define your style and your template as with any other control. For MenuItem, try something like this:
<ControlTemplate x:Key="{x:Static MenuItem.SubmenuItemTemplateKey}" TargetType="{x:Type local:MyMmenuItem}">
...
</ControlTemplate>
<ControlTemplate x:Key="{x:Static MenuItem.TopLevelHeaderTemplateKey}" TargetType="{x:Type local:MyMenuItem}">
...
</ControlTemplate>
<ControlTemplate x:Key="{x:Static MenuItem.SubmenuHeaderTemplateKey}" TargetType="{x:Type local:MyMenuItem}">
...
</ControlTemplate>
And to switch between different templates, we will use the RoleProperty dependency property, defining these triggers in our style:
<Style x:Key="MyMenuItemStyle" TargetType="{x:Type local:MyMenuItem}">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Style.Triggers>
<Trigger Property="Role" Value="TopLevelHeader">
<Setter Property="Template" Value="{StaticResource {x:Static MenuItem.TopLevelHeaderTemplateKey}}"/>
</Trigger>
<Trigger Property="Role" Value="TopLevelItem">
<Setter Property="Template" Value="{StaticResource {x:Static MenuItem.TopLevelItemTemplateKey}}"/>
</Trigger>
<Trigger Property="Role" Value="SubmenuHeader">
<Setter Property="Template" Value="{StaticResource {x:Static MenuItem.SubmenuHeaderTemplateKey}}"/>
</Trigger>
<Trigger Property="Role" Value="SubmenuItem">
<Setter Property="Template" Value="{StaticResource {x:Static MenuItem.SubmenuItemTemplateKey}}"/>
</Trigger>
</Style.Triggers>
</Style>
I hope this works for you; It worked for me when I faced the same problem.
Good luck, good code.

Member "BackGround" is not recognized or is not accessible

I'm relative new to WPF and I have check on several tutorials on how to style a DataGrid. All of them use the same examples but when I try to implement them into my project, came this annoying message.
This is the code I've been trying to implement, I got this from MSDN page:
<Window.Resources>
<!-- DataGrid style -->
<Style x:Key="DataGridStyle1" TargetType="{x:Type DataGrid}">
<Setter Property="ColumnHeaderStyle" Value="{DynamicResource ColumnHeaderStyle1}"/>
</Style>
<!-- DataGridColumnHeader style -->
<Style x:Key="ColumnHeaderStyle1" TargetType="DataGridColumnHeader">
<Setter Property="Height" Value="30"/>
<Setter Property="Background" Value="LightBlue"/>
<Setter Property="Foreground" Value="Blue"/>
<Setter Property="FontSize" Value="18" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="ToolTip" Value="Click to sort."/>
</Trigger>
</Style.Triggers>
</Style>
I'm using:
- C# Framework 4.5.1
- Blend for Visual Studio 2013
- Visual Studio 2013 (I got the error in both places).
All the imports and references are just fine.
I have check the solution properties and my Platform Target is "Any CPU"
My guess is this property might be deprecated for this control (DataGridColumnHeader).
Hope anyone could tell the proper way to acheive my goal.
Thanks in advance
It's trying to use a DynamicResource before it's defined.. Try swapping the Styles. Also, there's really no need for a DynamicResource here IMO, just change it to StaticResource.
<Window.Resources>
<!-- DataGridColumnHeader style -->
<Style x:Key="ColumnHeaderStyle1" TargetType="DataGridColumnHeader">
<Setter Property="Height" Value="30"/>
<Setter Property="Background" Value="LightBlue"/>
<Setter Property="Foreground" Value="Blue"/>
<Setter Property="FontSize" Value="18" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="ToolTip" Value="Click to sort."/>
</Trigger>
</Style.Triggers>
</Style>
<!-- DataGrid style -->
<Style x:Key="DataGridStyle1" TargetType="{x:Type DataGrid}">
<Setter Property="ColumnHeaderStyle" Value="{StaticResource ColumnHeaderStyle1}"/>
</Style>
</Window.Resources>

C# WPF - Disabled ComboBox should look like label

I'm trying to change the style of my combobox in wpf when it's disabled. It should look like a plain text (label).
Here is my code:
<Style TargetType="{x:Type ComboBox}">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="Black" />
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="BorderThickness" Value="0"></Setter>
<Setter Property="Background" Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
but it doesnt seem to work.
any hints?
You can add ControlTemplate, so the combobox will shown like a
TextBox(without border, background, toggle button, ect.). but it act
as a combobx(having drop-down list). Drop-down will not shown if the
control is disbled(hence it will shown like a label)
<ComboBox.Template>
<ControlTemplate>
<TextBlock Text="{Binding SelectedItem.MyText,RelativeSource={RelativeSource Mode=TemplatedParent}}"></TextBlock>
</ControlTemplate>
</ComboBox.Template>
If the control has a tendency to look like another control on certain condition, this kind of requirement can be satisfied by ContentControl. You can switch to appropriate content based on a given condition.
<ContentControl IsEnabled="True" /> // or IsEnabled="False"
Then switch via Style..
<Style TargetType="{x:Type ContentControl}">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="true">
// combobox
</Trigger>
<Trigger Property="IsEnabled" Value="false">
// Label
</Trigger>
</Style.Triggers>
</Style>
Just place two controls, the ComboBox and the Label. Bind the Visibility property of each to your boolean indicating if the ComboBox should be enabled so that one is visible when enabled and the other when disabled.

Disable the "IsEnabled=false" Color Change on a Button?

I want to Avoid the Color Change of a Button when it gets disabled.
The Button Color should be the Same if its diabled or not.
Using a style I can change the Background Color when it gets disabled:
<Style TargetType="{x:Type Button}">
...
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
...
<ControlTemplate.Triggers>
...
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="Border" Property="Background" Value="#EEEEEE" />
<Setter TargetName="Border" Property="BorderBrush" Value="#AAAAAA" />
<Setter Property="Foreground" Value="#888888"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I can change the Background color there, but I want to keep it dynamic because the Background Color is databound and should not change.
If I delete the Background setter, the default background color change is performed.
How can I disable the colorchange? Or at least make the Disabled-Background-Color databound?
Sorry for my bad english.
If you want to make it data-bonund most appropriate place, imo, is declaring it inside relative DataTmplate of your control, where you specify the Style (already defined by you) and data applied to the control.
There you can define a Converter between some your state and relative color you would like to appear on the button.
OR
If you would like to limit yourself in Style, you can define a databinding inside Style itself. Imo not very logical, but it is possible.
Have a look on this answer:
Change Button Background color through MVVM pattern in WPF
I know this is late but hopefully it helps someone. This is how I would setup the style:
<Style TargetType="Button">
...
<Style.Triggers>
<Trigger TargetType="Button" Property="IsEnabled" Value="false">
<Setter TargetName="Border" Property="Background" Value="#EEEEEE" />
<Setter TargetName="Border" Property="BorderBrush" Value="#AAAAAA" />
<Setter Property="Foreground" Value="#888888"/>
</Trigger>
</Style.Triggers>
</Style>
You need to include the TargetType again in the Trigger or else you'll get an exception.

setting the TabItem IsSelected background

I can't seem to control the background color of the selected tab. I can use the IsSelected trigger to control the value of the non-selected tabs however.
This code:
<Style TargetType="{x:Type TabItem}">
<Setter Property="Background" Value="Black" />
<Setter Property="Foreground" Value="#EE444444" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="false">
<Setter Property="Background" Value="Pink"/>
</Trigger>
</Style.Triggers>
</Style>
works, in setting the un-selected tabs background to pink. However, the selected tabs following some light gray color I can't get rid of.
I also tried this:
<Style TargetType="{x:Type TabItem}">
<Setter Property="Background" Value="Black" />
<Setter Property="Foreground" Value="#EE444444" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="false">
<Setter Property="Background" Value="Pink"/>
</Trigger>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
but none of these have any affect on selected tab. The only thing I can think of is that some referenced assembly has a generic tab style?
This style is located in the same file as the tab control, in the Grid.Resources section.
the TabItem selection behaviour is defined at the Template level. If you want to change the color, define a whole new DataTemplate, and define triggers in that template to change color. Then define that template as the ItemTemplate of your TabControl.

Categories

Resources