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
Related
XAML
<utility:InvalidNotification x:Name="InvalidNotificationControl"/>
<Button Content="Clean AppV Cache" Click="Button_Click">
<Button.Style>
<Style TargetType="Button">
<Setter Property="IsEnabled" Value="True"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=InvalidNotificationControl, Path=Visibility}" Value="Visible">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
NOTE
InvalidNotification is a custom UserControl
Now, the DataTrigger works fine initially and disable the button since the Usercontrol is visible.
The problem is when I collapse the Usercontrol based on another condition the button stays disable. I found this related answer which states that The properties changed by triggers are automatically reset to their previous value when the triggered condition is no longer satisfied. which is not my case. Why is that ?
EDIT
Thanks to #mm8 which led me to the solution. So if ever you're trying to bind a control on a UserControl's content (inner TextBlock in my case), just add a second trigger at the bottom of your Usercontrol like so,
<UserControl.Style>
<Style TargetType="UserControl">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=Notification, Path=Visibility}" Value="Visible">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Style>
where notification would be the name of my TextBlock
Your example works provided that you toggle/set the Visibility property of the InvalidNotification control itself, since it is this property that you bind to.
If you set the Visibility property of some element within the InvalidNotification control, you need to bind to this specific element.
You can't do this using an ElementName binding though because the Button and any element defined in the InvalidNotification control don't belong to the same namescope.
Is there a way (using data binding or simply xaml) to set the background of all elements in a view to one color, and all text to another?
I know I can edit each element in the view one by one, but I I'd like to see if this is possible with settings at a global level. Kind of like how everything by default is set to black on white.
I guess what I'm asking is if there is a feature/setting of a WPF application that offers what I'm looking for, and/or what I should search to find an answer online.
My project isn't using anything but what visual studio offers when you create a WPF project, so I can't use a prism or mvvm light approach.
Thanks in advance for your answer!
Globally...or simply XAML...
if there is a feature/setting of a WPF application that offers what I'm looking for
In Application Resource add style like this:
<Style TargetType="Control">
<Setter Property="Background" Value ="Blue"/>
<Setter Property="Foreground" Value ="Red"/>
</Style>
<Style TargetType="TextBlock">
<Setter Property="Background" Value ="Blue"/>
<Setter Property="Foreground" Value ="Red"/>
</Style>
Based on your target element you want to set background.
When you say "the background of all elements in a view" you should be more specific, If by 'element' you mean UIElement then there is no Background property in UIElement. If it means Control then not all UIElementsderive from Control (e.g. TextBlock) and finally if it means every UIElement derived type defined in your view that have a Background property, then you should add different styles for each type without setting the x:key to the YourView.Resources like this:
<Window.Resources>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Background" Value="Red" />
<Setter Property="Foreground" Value="Blue" />
</Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Red" />
<Setter Property="Foreground" Value="Blue" />
</Style>
...
</Window.Resources>
uses controls collection through which you can control all controls in WPF
I have a dialog with buttons - the buttons text and functionality are dynamic and changing according to the user's needs.
In most cases the button style is the default style, in case the button is an OK button, I would like the button to use a different style.
I've tried to add a trigger that will change the button style according to a Boolean property:
(when IsOKButton=true use the "RedButtonStyle")
<Button.Template>
<ControlTemplate >
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding IsOKButton}" Value="True">
<Setter Property="Style" Value="{StaticResource RedButtonStyle}"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
the RedButtonStyle is a resource style that can be used in diffrent projects for a diffrent buttons type , so the soultion should be in my project and can't be in the resource style itself.
But when using this trigger I get an exception.
"set property system.windows.controls.control.template threw an exception"
Can anyone help me resolve this problem, or suggest an idea to set the style dynamicly?
Thanks
You could put the trigger in the style itself:
<Style x:Key="OKButtonStyle">
<Style.Triggers>
<DataTrigger Binding="{Binding IsOKButton}" Value="True">
//Whatever Property is different in the OKButtonStyle
</DataTrigger>
<DataTrigger Binding="{Binding IsOKButton}" Value="False">
//Set it back to default
</DataTrigger>
</Style.Triggers>
</Style>
Then just give your button the style OKButtonStyle from the start.
If want to make your OK Button mostly the same as a more general style which you want all your buttons to have you can just base it on the general one like this:
<Style x:Key="OKButtonStyle" BasedOn="{StaticResource GeneralButtonStyle}">
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.
I use Styles to define what happens when a user hovers over an image like this.
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="c:\\2.bmp"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Source" Value="C:\\1.bmp"/>
</Trigger>
</Style.Triggers>
</Style>
But, I guess for all the images that I include in my application, the same images defined in 'Value' attributes are used. What If I need a different on-hover image for different Images without this custom overriding?
In this case, any ideas what I should use? Or what is the better way to handle hovering of images in WPF?
We should define a x-key value like Jon suggested!
<Style x:Key="Name_of_your_style" TargetType="{x:Type Image}">
<Setter Property="Source" Value="c:\\2.bmp"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Source" Value="C:\\1.bmp"/>
</Trigger>
</Style.Triggers>
and while using this snippet use something like
<Image Style="{StaticResource Name_of_your_style}" Name="I1" />
<Image Name="I2" />
This will make the image I1(defined first) to use the above template(on hover handled) while the other image remains as per your current template.
You can define several different styles and give them an x:Key value, rather than a TargetType value. You can then simply set the Style attribute of your images to the x:Key of the appropriate style.
If you want to apply a single style to the majority of your Images, but you want to override it for just a few of them, then you can combine the two methods. If you assign a style to a type of element (via the TargetType attribute), you can override this on specific elements by explicitly specifying their Style attribute. Also, if you set Style={x:Null}, you can make an element revert to the default style.