WPF ControlTemplate - default style - c#

I want to use the default style of buttons and just want to add a Grid and Stackpanel with 2-3 Bindings. When i add the ControlTemplate in my Style all Trigger-, Border-, ...settings are overwritten. How can i just add my Grid/Stackpanel/Bindings while using the rest of the default settings?
<Style x:Key="listbutton">
<Setter Property="Button.Height" Value="40"/>
<Setter Property="Button.Margin" Value="0,3"/>
<Setter Property="Button.Template">
<Setter.Value>
<ControlTemplate>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

The purpose of a ControlTemplate is to define how a Control must be displayed. You can't have a ControlTemplate based on another ControlTemplate (it wouldn't make sense). What you can do is take the default ControlTemplate and modify it at your will.
The default ControlTemplate for Button can be found here

Related

Style BasedOn a style defined in ControlTemplate Resources

I'm using a 3rd party ContentControl which comes with the following theme:
<Style TargetType="{x:Type xyz:XyzControl}" x:Key="XyzControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type xyz:XyzControl}">
<ControlTemplate.Resources>
<Style TargetType="Button">
<!-- A lot of styling... -->
</Style>
</ControlTemplate.Resources>
<!-- More template stuff... -->
I want to add some DataTriggers to buttons inside this control but I want to keep the default styling from the control theme.
<xyz:XyzControl>
<Button>
<Button.Style>
<Style TargetType="Button" BasedOn="{???}">
<Style.Triggers>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</xyz:XyzControl>
I tried to base on {StaticResource {x:Type Button}} but this loads the default global button style, not the default style in this context.
This is not possible since you can't base a ControlTemplate on another ControlTemplate. You will have to re-define the entire template as a whole:
WPF: Is there a way to override part of a ControlTemplate without redefining the whole style?
And adding a trigger to a Style won't affect or "override" the triggers that are defined in the ControlTemplate of the control so you will have to override the entire ControlTemplate from scratch.
You could of course copy the default one into your XAML markup and edit it as per your requirements.
Add a key to the 3rd party's button style :
<Style TargetType="Button" x:key="xyzbuttonStyle">
then :
<Style TargetType="Button" BasedOn="{StaticResource xyzbuttonStyle}">

WPF using style that contains another style

I'm trying to make a progress bar style that is re-usable.
So the idea here is very simple. I have a style already with target type ProgressBar, and it's just a spinny circle that fills as it goes from 0-100%. However, in order to make it re-usable and modular, I do not want to hard-code the text that goes along with it - it should be optional.
So I want to create another style that DOES include text "Downloading... X/Y MB". For this I take Value for X, Maximum for Y, and Tag for the unit. I want to include the same spinny circle thingy for the graphical part on the left. How can I do this? With BasedOn property, I think you can only set something already there to be different. What if I want to add additional elements (like textblocks in this case)?
If only text value differentiates then within style you can bind propertie's value to parent's property like Tag where at every single either style or element you adjust it to specific requirement.
<Window.Resources>
<Style x:Key="FirstButtonStyle" TargetType="Button">
<Setter Property="Content" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ContentPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="SecondButtonStyle" TargetType="Button" BasedOn="{StaticResource FirstButtonStyle}">
<Setter Property="Content" Value="2"/>
</Style>
</Window.Resources>
<StackPanel>
<Button Style="{StaticResource FirstButtonStyle}"/>
<Button Style="{StaticResource SecondButtonStyle}"/>
</StackPanel>
The outcome is 1 and 2. If your intent is to inject some UI element within style then there is no such an option, alas. Style needs to be rewritten once again.

Bind column header visibility without losing global style

I want to bind the column header visibility of a wpf listview to a dependency property without losing the global style (expression dark) I used.
I defined a style:
<Style x:Key="myHeaderStyle" TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Visibility" Value="{Binding ColumnHeaderVisibility}" />
</Style>
Then I applied it like this:
<GridView ColumnHeaderContainerStyle="{StaticResource myHeaderStyle}">
I'm using the expression dark theme. It's imported via MergedDictionaries and can be changed in runtime.
Everything is fine when the column header is invisible. But when visible it is shown in default windows style, because setting the ColumnHeaderContainerStyle overrides the expression dark style.
Using "BasedOn" on the original style is no option, because all resources are dynamic due to the requirement to change style in runtime. BasedOn only works on static resources, which won't allow changing in runtime.
What else can I do?
Not sure if this will work but you can try to base style on the default style.
<Style x:Key="myHeaderStyle" TargetType="{x:Type GridViewColumnHeader}" BasedOn="{StaticResource {x:Type GridViewColumnHeader}}">
<Setter Property="Visibility" Value="{Binding ColumnHeaderVisibility}" />
</Style>

WPF: TextTrimming on a ContentPresenter

Is there a simple way to just get TextTrimming to work with a ContentPresenter?
I have implict styles for TextBlock and AccessText that have TextTrimming set to CharacterEllipsis, but it's not picked up by the ContentPresenter. I can change the ContentPresenter to an AccessText or TextBlock and set it there, but then the template only handles text content.
Any suggestions?
Thanks!
Implicit Styles for elements that derive from UIElement, but not Control, are not applied if the element is defined in a control's Template unless the implict Style is defined in the application Resources. The same holds true for TextBlocks used by ContentPresenter.
For example, in the following XAML the TextBlock that is ultimately used to present the button's content will not get the implicit Style:
<Window.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Red" />
</Style>
</Window.Resources>
<StackPanel>
<Button Content="Will not be red" />
<TextBlock Text="Will be red" />
</StackPanel>
If you take that exact same Style and move it to the application's Resources, then both will be red:
<Application.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Red" />
</Style>
</Application.Resources>
So you can either move your implicit Style to application resources, which is generally not a good idea. Or you can customize the display for the specific scenario you have. This can include adding an implicit DataTemplate, or customizing a control's Template.
If you can provide more information, then it would be easier to know which is the best approach.
Thanks to this Gist by James Nugent: "WPF style which puts character ellipsis on button contents without replacing the ContentPresenter with a TextBlock and thus losing the ability to support access keys."
This worked for me:
<ContentPresenter.Resources>
<Style TargetType="TextBlock">
<Setter Property="TextTrimming" Value="CharacterEllipsis"></Setter>
</Style>
</ContentPresenter.Resources>

GridViewColumn content and VerticalAlignment

i want to display some information in a listview using the GridView.
i have several GridViewColumns and everything works fine.
However, want the GridViewColumns content to have a VerticalAlignment (Top in this case)
but the gridvewcolumn intself doesnt offer a VerticalContentAlignment dependency property.
when using DisplayMemberBinding there is also no possibility to supply
VerticalAlignment information.
When using a custom DataTemplate as Celltemplate, i can add a VerticalAlignment="top" dp to e.g. some textblock. however this does not work.
is there any "nifty-grifty special magic trick" to fullfill this tasK?
(
You can apply this style to your ListView:
<Style TargetType="{x:Type ListView}">
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="ListViewItem">
<Setter Property="VerticalContentAlignment" Value="Top"/>
</Style>
</Setter.Value>
</Setter>
</Style>

Categories