I have to apply the following style to my ListViewItem:
<UserControl.Resources>
<local:Look x:Key="ListViewItemLook" Background="Magenta"/>
<Style x:Key="ListViewItemStyle" TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{Binding Source={DynamicResource ListViewItemLook}, Path=Background}"/>
</Trigger>
</Style.Triggers>
</Style>
But i get an exception, i try to change:
<Setter Property="Background" Value="{Binding Path=Background}"/>
And add to the Style:
<Setter Property="DataContext" Value="{DynamicResource ListViewItemLook}"/>
But is does not work. I can't bind to a StaticResource because I need to set the BackGround property run-time.
What have I to do? Thanks.
If you want both local:Look and the setter to refer to the same color, perform a small refactor:
Pull the color out into a separate SolidColorBrush and make both items refer to it:
<SolidColorBrush x:Key="SelectedListViewItemBackground" Color="Magenta" />
<local:Look x:Key="whatever" Background="{StaticResource SelectedListViewItemBackground}" />
<Setter Property="Background" Value="{StaticResource SelectedListViewItemBackground}" />
If you're trying to do something else, I can't figure out what it is because the question doesn't make sense.
As far as I am aware, DynamicResource extension uses the DependencyProperty mechanism (pretty much like a binding). Therefore you cannot set Source property of a Binding object with DynamicResource because it is not a DependencyProperty.
In addition, if you want to change the Background property of Look but not the Look itself in resources; then setting Look as a static resource to the binding property should not be a problem. Of course Background property of Look class should either trigger a PropertyChanged event or be a DependencyProperty itself.
Related
I've been reading through WPF Unleashed and something has confused me about styles.
<Style TargetType="{x:Type Control}" x:Key="altStyle">
<Setter Property="Background" Value="Green"></Setter>
<Setter Property="Foreground" Value="White" ></Setter>
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="White"></Setter>
<Setter Property="Foreground" Value="Black" ></Setter>
</Trigger>
</Style.Triggers>
</Style>
So I have a style here which can be applied to anything that derives from control. Assuming that's how the TargetType works. The confusing part for me is how it understands what ItemsControl.AlternationIndex is. I'm defining a style for a control, which is higher up the inheritance chain than ItemsControl. It's seems to break the rules of inheritance.
I then have a simple datagrid which uses this style as its ItemsContainerStyle:
<local:MyGrid AlternationCount="2" ItemsSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DataContext.Source}" Grid.Row="3" ItemContainerStyle="{StaticResource altStyle}"></local:MyGrid>
(MyGrid derives from DataGrid)
I'm assuming here that the style is applied to each DataRow in the grid, but how on earth is able to resolve this ItemsControl.AlternationIndex as this certainly does not apply to a DataRow does it? and just for clarity on how it looks:
So the question is. How does a style that applies to a datagrid row manage to resolve a property called ItemsControl.AlternationIndex
As an attached property the AlternationIndex can be set on any dependency object and can potentially be inherited. When the style queries the rows it will find that the attached property has been set on them by the creating ItemsControl (the grid control).
I've created a ResourceDictionary that defines a bunch of System.Windows.Shapes.Path that are used in the ContentPresenter of a Button ControlTemplate.
I'd like to change one of the Paths out based on a ViewModel property. If true the button uses one path from the ResourceDictionary, if false a different one.
Currently I just reference a StaticResource in the xaml to point directly to the path I want displayed.
What's the best way to do this?
You would have to modify the content template of the button in style by referring to the elements from you resource dictionary.
Something like this:
<Button.Style>
<Style TargetType="Button">
<Setter Property="ContentTemplate" Value="{StaticResource cp2}"></Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource cp1}"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
I have used mouse over property as my trigger to change the content template.
You can use DataTrigger instead of Trigger
I am using MahApps and working on implementing validation for TextBoxes. MahApps provides some nice properties in TextBoxes, as Controls:TextBoxHelper.Watermark and Controls:TextBoxHelper.ClearTextButton. I am writing an ErrorTemplate using my style but I overwrite the default template of the TextBox and lose those Metro properties. How can I achieve my goal without losing the template:
<Style TargetType="TextBox">
<Setter Property="Validation.ErrorTemplate" Value="{DynamicResource ErrorToolTipTemplate}" />
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
</Trigger>
</Style.Triggers>
</Style>
You should define your new style based on existing to keep everything it has. I guess in case of MahApps it will be MetroTextBox:
<Style TargetType="TextBox" BasedOn="{StaticResource MetroTextBox}">
<!-- your properties go here -->
</Style>
The BasedOn is the key to success. However, it's likely, that you're using MahApps controls not in just one place. Therefore, try to make your style more generic and avoid direct references to MetroTextBox resource in the BasedOn.
The more good looking XAML style would be like that:
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<!-- your properties go here -->
</Style>
Is there a way to do this, or do I have to create an IsSelectedProperty on the ViewModel and Bind to that instead?
I would like to be able to do something like Source={Binding RelativeAncestor ListViewItem}
but instead there is only this property sourcename which I can use to set triggers based off of the items in the datatemplate if I name them using x:Name
<HierarchicalDataTemplate.Triggers>
<Trigger SourceName="" Property="IsSelected" Value="True">
<Setter TargetName="bdr" Property="Foreground" Value="White"/>
<Setter TargetName="bdr" Property="Foreground" Value="Red"/>
</Trigger>
</HierarchicalDataTemplate.Triggers>
Looking back, I realized that yesterday I made a very confusing post. Also, considering how hard I find it to even interpret people's comments to my questions, I should probably give more detail.
I know that in wpf you can set triggers based on the control by setting a style for the target control type.
In addition you also have data triggers that can trigger off of properties in the datacontext. What I was hoping was that there was a way to use triggers, or datatriggers to set a property when the datacontext is an object of a specific type.
is this possible? If not, I will just accept the provided answer as applicable in my situation, but since this will require me to add a property to my viewmodel, it seemed reasonable to check if there was a way to just check item type rather than having to check the actual property.
I would suggest that you bind the IsSelected property in your view model, but that's just me.
I'm not sure how complex your HierarchicalDataTemplate is, or if some items need to have their Foreground changed, and some don't; but I'm going to assume you want to update the item that is selected throughout the entire TreeView (if that's what this is for).
If that is the case, just add DataTriggers to the Style of the TreeViewItem:
<Style TargetType="TreeViewItem">
<Setter Property="IsSelected"
Value="{Binding IsSelected, Mode=TwoWay}" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<Setter Property="Foreground"
Value="Red" />
</DataTrigger>
<DataTrigger Binding="{Binding IsSelected}"
Value="False">
<Setter Property="Foreground"
Value="Black" />
</DataTrigger>
</Style.Triggers>
</Style>
Note that you don't need to bind the IsSelected parameter if you don't want to, its just there because it's in my code.
I've made an application resource with a style which should be triggered if the textbox has the "IsReadOnly" property. Looks like this:
<Application.Resources>
<Style TargetType="{x:Type TextBox}" >
<Style.Triggers>
<Trigger Property="IsReadOnly" Value="True">
<Trigger.Setters>
<Setter Property="Background" Value="Black" />
</Trigger.Setters>
</Trigger>
</Style.Triggers>
</Style>
</Application.Resources>
However, the program doesn't react to this. It works when I use IsEnabled=True. However IsEnabled=False doesn't work either. So, question: Do the triggers only work if you check for "True"? And is IsReadOnly not supported at all? If so: How do I know which control properties are actually supported?
See an answer for this problem by following the provided link:
DataTrigger problem with textbox