How to use style from another resource in xaml - wpf

I need to change ScrollBar in my particular ListBox control. I have a ScrollBar style in another resource. But I don't know how to apply it. For example, I can apply a template from another resource, like this:
<ListBox
<ListBox.Resources>
<Style TargetType = "ScrollBar">
<Setter Property="Template" Value="{DynamicResource MyScbTemplate}"/>
</Style>
</ListBox.Resources>
</ListBox>
But I can't do the same with Style, like this:
<Style TargetType = "ScrollBar">
<Setter Property="Style" Value="{DynamicResource MyScbStyle}"/>
</Style>

You're on the right lines, you can't set the Style's Style inside the Style. (Yep.)
Instead, you need to inherit the parent style, like this:
<Style TargetType="ScrollBar" BasedOn="{DynamicResource MyScbStyle}">
For some more reading on BasedOn, see here.

Related

Conditional BasedOn in XAML styles

Given:
<Style x:Key="ThirdLevelGroupBoxStyle" TargetType="GroupBox" BasedOn="{StaticResource MetroGroupBox}">
<Setter Property="Background" Value="{DynamicResource AccentColorBrush3}" />
</Style>
<Style x:Key="SecondLevelGroupBoxStyle" TargetType="GroupBox" BasedOn="{StaticResource MetroGroupBox}">
<Setter Property="Background" Value="{DynamicResource AccentColorBrush2}" />
</Style>
<Style TargetType="GroupBox" x:Key="WidgetControlTemplateStyle" BasedOn="{StaticResource ThirdLevelGroupBoxStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding CanExecuteClickCommand}" Value="True">
<!-- TODO: SecondLevelGroupBoxStyle -->
<Setter Property="Background" Value="{DynamicResource AccentColorBrush2}" />
</DataTrigger>
</Style.Triggers>
</Style>
<ControlTemplate TargetType="ContentControl" x:Key="WidgetControlTemplate">
<GroupBox ... Style="{StaticResource WidgetControlTemplateStyle}">
<ContentPresenter />
</GroupBox>
</ControlTemplate>
ControlTemplate has style WidgetControlTemplate. I want to base (BasedOn) the WidgetControlTemplate style conditionally on ThirdLevelGroupBoxStyle or SecondLevelGroupBoxStyle, in order to avoid XAML duplication. Is there way to achieve this?
If I can't do that, I have to duplicate the definition of SecondLevelGroupBoxStyle.
Is there way to achieve this?
No, not in XAML. The base style to base the style on must be known at design-time.
If I can't do that, I have to duplicate the definition of SecondLevelGroupBoxStyle.
Since you have two different styles that are based on MetroGroupBox, each style that is based on either of this will always be a separate style because you cannot base a single style on more than one style.
What you could do is to use a trigger that sets the Background property of the GroupBox to either AccentColorBrush3 or AccentColorBrush2 instead of trying to inherit this property from another style. It seems like you are already doing this in your WidgetControlTemplateStyle style. And yes, if the ThirdLevelGroupBoxStyle/SecondLevelGroupBoxStyle sets more than one property you will have to set all these in the WidgetControlTemplateStyle as well.
I am afraid there is no way around this unless you merge your two style into one or define them programatically somehow.

XAML separate binding of ContainerStyle and ContentTemplate in ListBox

I tried this for a while now and searched in the web without success... Now I dare to ask on stackoverflow myself.
So, the aim is to separate the definitions of the ItemContainerStyle and the ContentTemplate of a ListBoxItem. I have defined the ListBoxItemStyle in a ResourceDictionary and two different DataTemplates in the Window.Resources.
I now like to set the style of the ListBoxItem according to the one defined in the ResourceDictionary and change the DataTemplate with a trigger (IsMouseOver).
My (not working) Code so fare looks like this:
<ListBox HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="20,60,10,10"
Grid.Row="1" Grid.Column="0"
PreviewMouseMove="DragMove_PreviewMouseMove"
PreviewMouseLeftButtonDown="Drag_PreviewMouseLeftButtonDown"
ItemsSource="{Binding Persons}" VerticalContentAlignment="Center"
Style="{StaticResource DefaultListBoxStyle}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Style" Value="{StaticResource DefaultListBoxItemStyle}"/>
<Setter Property="ContentTemplate" Value="{StaticResource PersonsListBoxItemTemplate_default}"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource PersonsListBoxItemTemplate_infoButtons}"/>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
where DefaultListBoxStyle is the style defined in the ResourceDictionary and PersonsListBoxItemTemplate_default & PersonsListBoxItemTemplate_infoButtons are the DataTemplates defined in the Window.Resources.
Now I get an error, that the style-object must not have an impact on the style-property of the object it belongs to.
I tried different ways, but without success... I also tried to define the style first and then change the template, but it does not work either.
Thank you all for your help!
So you can't set Style Property in Style with Setter. For this you need to use BasedOn:
<Style TargetType="ListBoxItem" BasedOn="{StaticResource DefaultListBoxItemStyle}">
<Setter ... />
</Style>

Override item Style Template with a DataTemplateSelector

I've got a Style on ListViewItem that sets the Theme property
<Style x:Key="{x:Type ListViewItem}" TargetType="{x:Type ListViewItem}">
<Setter Property="Template" Value="{StaticResource ListViewItemTemplate}"/>
</Style>
However, in one of the cases where I'm using a ListView I want to use a DataTemplateSelector to determine which Template to use
<Style x:Key="MyListStyle" TargetType="{x:Type ListView}" BasedOn="{StaticResource {x:Type ListView}}">
<Setter Property="ItemTemplateSelector" Value="{StaticResource MyItemTemplateSelector}"/>
</Style>
It's applied like this
<ListView Style="{StaticResource MyListStyle}/>
However, it would appear that the Style on the item takes over and that style is applied to all the items in the ListView. I found this question which had a similar problem, however, the solution simply doesn't use the Template on the Item style at all. I need to keep that.
I've played around with the ContentTemplateSelector by restyling the ListViewItems in that ListView
<Style x:Key="MyItemStyle" BasedOn="{StaticResource {x:Type ListViewItem}}" TargetType="{x:Type ListViewItem}">
<Setter Property="ContentTemplateSelector" Value="{StaticResource MyItemTemplateSelector}"/>
</Style>
However, the Template on the other style is used instead. If I try nulling the Template then nothing shows up at all!
<Setter Property="Template" Value="{x:Null}"/
Is there a way that I can replace the Template on the ListViewItems for a given ListView while keeping the rest of my Style?
I was unable to override the Template set on the ListViewItem in the ListView Style.
To get around this I replaced the Template on the ListViewItem with another ItemTemplateSelector in my base ListView Style. This selector always returns my original Template. In my ListView child Style the new ItemTemplateSelector is used.

Create Style for a StackPanel and its Contents

I want to create a style for Stackpanels using a key. This style will be in a global ResourceDictionary for use everywhere in the application. But it should not only set the style of the Stackpanel, but also its content.
I want to use the stackpanel like this:
<StackPanel Style="{StaticResource GlobalStackPanelStyle}">
<Button>test</Button> <-- the button style should also be defined due to the Stackpanel style
</StackPanel>
How should the Resourcedictionary look like if for example all the containing buttons should be green?
You would have something like this in your resource dictionary:
<Style TargetType="StackPanel" x:Key="GlobalStackPanelStyle">
<Style.Resources>
<Style TargetType="Button">
<Setter Property="Background" Value="Green" />
</Style>
</Style.Resources>
</Style>

Dynamic highlight color in ListView

How can I make background highlight color dependent on some property of ListViewItem?
This is an issue that people often ask for. Actually, for some reasons, when an item is selected in a ListView or ListBox, the Background color is not the one that is changed. It is a bit more tricky. In fact you need to override the value of the static color resources to which the item template is bound. So to change the higlighting colors of the items you have to do like this:
<ListView>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Orange"/>
</Style.Resources>
</Style>
</ListView.ItemContainerStyle>
</List>
Here is a more developed explanation: Trigger for ListBoxItem
EDIT:
For changing selected background, you will have to override the ListViewItem's Template.
See this... http://msdn.microsoft.com/en-us/library/ms788717(v=vs.90).aspx.
Replace the {StaticResource SelectedBackgroundBrush} with your preferred background brush in the template.
To change backgrounds based on ANY other property that the control template does not rely upon, You can use triggers ...
<ListView ...>
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<Trigger Property="SomeListViewItemProperty" Value="Value1">
<Setter Property="Background" Value="Red" />
</Trigger>
<Trigger Property="SomeListViewItemProperty" Value="Value2">
<Setter Property="Background" Value="Yellow" />
</Trigger>
</Style.Triggers>
</Style>
<ListView.Resources>
</ListView>
I hope this answers your question.

Resources