Change Expander Text Expanded/Collapsed AND have different font size - wpf

So the following does the first part:
<Expander>
<Expander.Style>
<Style TargetType="Expander">
<Setter Property="IsExpanded" Value="False" />
<Setter Property="Header" Value="See More" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsExpanded,RelativeSource={RelativeSource Self}}" Value="True">
<Setter Property="Header" Value="See Less" />
</DataTrigger>
</Style.Triggers>
</Style>
</Expander.Style>
</Expander>
But what if I want the header size to be 16pt too? Can't think of the correct syntax.

There is no direct way of modifying header. You need to create custom template to change property of header only.
But there is a easy workaround which I used. You can change the font size in the trigger for the full expander like <Setter Property="FontSize" Value="16"/>. And have the fontsize of children explicitly set to 12(or the default value) or also can bind the children fontsize to the expander's parent fontsize. This will make expander children to remain as 12 or to expander's parent fontsize and trigger will not have any affect on them, so only header will be changing.

Related

How to make a styled DataGridCheckBoxColumn to respect DataGrid.IsReadonly?

I have DataGrid.IsReadonly bound to a property that changes based on a condition. The DataGrid contains a DataGridCheckBox column that I had to style in order to center it vertically in a cell.
However, after applying a style the check box column does not respect the parent's IsReadonly value. That is, regardless of its value the checkbox can be clicked on and changed. I've seen quite a number of posts dealing with somewhat similar situations but could not find a reliable solution.
Could someone please let me know how to style the checkbox column so it respects its parent griddata's IsReadonly? Any theory behind it would also be appreciated.
This how I apply the style:
<Style x:Key="CenterStyleCB" TargetType="{x:Type CheckBox}">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
<DataGridCheckBoxColumn ... ElementStyle="{StaticResource CenterStyleCB}" />
Add the following code into your style:
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Column.IsReadOnly, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGridCell}}}" Value="True">
<Setter Property="IsHitTestVisible" Value="False" />
</DataTrigger>
</Style.Triggers>
If your DataGrid is always ReadOnly, then I would suggest you skip the trigger and use the setter directly.

How to modify legacy named style for having different setters based on targetTypes?

I have this named style
<Style x:Key="validationSupport" TargetType="{x:Type Control}">
<Setter Property="Margin" Value="5,2,14,2" />
...OMISSIS...
<Style.Triggers>
...OMISSIS...
<DataTrigger Binding="{Binding DataContext.ActiveWorkspace.Editable, RelativeSource={RelativeSource AncestorType=Window}}" Value="False">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
I use it extensively for TextBoxes, ComboBoxes, DatePickers etc, so I used as TargetType a super class for all these elements, Control.
Now I would like to differentiate the setter inside the dataTrigger using specific properties that 'Control' doesn't have. It seems I have to create different styles with different names,each for every targetType I want to differentiate, but that way I have to change the style name inside all elements which use it. Is there a smarter way to achieve that goal ? I don't want want to go and modify every xaml file I have.
Update after first answer
I have tried to put the following setters inside the datatrigger:
<Setter Property="Background" Value="#FFECECF8" />
<Setter Property="CheckBox.IsEnabled" Value="False" />
<Setter Property="DatePicker.IsEnabled" Value="False" />
<Setter Property="ComboBox.IsEnabled" Value="False" />
<Setter Property="TextBox.IsReadOnly" Value="True" />
Unfortunately the tests gave odd results. The IsEnabled property is set for TextBoxes too despite the prefix should limit its application to CheckBoxes, DatePickers and ComboBoxes.
My final need was to make some control contents unchangeable avoiding the difficult to read colors associated with disabled controls. From previous researches I understood that changing the colors for a 'disabled' control is not an easy task and involves the redefinition of the control template. So I thought to apply a combination of IsReadOnly and Background, but it is not applicable for the above problem. In fact CheckBoxes, DatePickers and ComboBoxes can only be made unchangeable using the IsEnabled property.
Am I missing something ?
There is a way, but I have to warn you - this is far from best-practice and should be avoided
WPF allows you to use desired type as a prefix for the property. That way, if you apply the style to a control that doesn't inherit from the prefixed type - the setter is ignored.
<Style x:Key="validationSupport" TargetType="{x:Type Control}">
<Setter Property="Margin" Value="5,2,14,2" />
...OMISSIS...
<Style.Triggers>
...OMISSIS...
<DataTrigger Binding="{Binding DataContext.ActiveWorkspace.Editable, RelativeSource={RelativeSource AncestorType=Window}}" Value="False">
<Setter Property="IsEnabled" Value="False" />
<Setter Property="Button.Background" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
[Test this extensively, since I suspect that it might create memory leaks.]

Use trigger to change colour of a path declared in ResourceDictionary

I'm creating a radiobutton style. The RadioButton has a Border which hosts a ContentControl. The ContentControl has its Content property set to a Path (FemaleVector) declared in a separate ResourceDictionary. How can I change the Fill property of the path when the radiobutton IsChecked? Below is what I have so far. I am able to change the background property of the border but setting the Foreground property of the ContentControl does not change the colour of the path. (Didn't think that would work.)
<Style x:Key="Female" TargetType="{x:Type RadioButton}">
<Setter Property="Margin" Value="0,0,5,0"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<Border x:Name="border" Padding="7,3,7,3" Width="35" Height="35" BorderBrush="#8CD567DC" Background="#00D567DC" CornerRadius="5" BorderThickness="0.8">
<ContentControl x:Name="content" Content="{DynamicResource FemaleVector}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" TargetName="border" Value="#8CD567DC"/>
<Setter Property="Foreground" TargetName="content" Value="Blue"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I don't like having the long Data property of paths in my Styles, so I have moved them into a separate ResourceDictionary. Should I just put the Path back into my Style instead of keeping it in a separate ResourceDictionary?
Edit: similar questions are here and here.
If the style is not reused somewhere, I would personally keep it in local style resources section. That way you see bigger picture. Otherwise it would be wise to keep it in ResourceDictionary :)
Either way you should be able to change Fill property with:
<Setter Property="Content.Fill" TargetName="content" Value="Blue"/>
If this is not working, I advise few ways more:
You can use Trigger.EnterActions<> in Xaml. Perhaps setting property through animation will have better effect? ControlTemplate triggers with setters are sometimes way limiting.
There's also relative binding. But you gotta be careful with that. (If you pla to make it reusable)
In your FemaleVector style, you can bind Fill against ContentControl Foreground. Look for RelativeBinding in Google.
And then there's property inheritance. If you set Fill color in FemaleVector, you need to do it with style. Such as:
<Style>
<Setter Property="Fill" Value="BLACK" />
</Style>
you can later set ContentControls Style and add trigger there, like:
<ContentControl.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding={Binding IsChecked, RelativeSource={RelativeSource AncestorType=RadioButto}} Value=TRUE>
<Setter Property="Path.Fill" Value="BLACK" />
</DataTrigger>

Customize Expander to expand on mouse enter

I am using Expander in WPF to display my data. The default style for the Expander control contains a toggle button which shows/hides my content when I click on it.
How can I modify the style so that it expands when I hovers the mouse over the header and collapse when I move away?
Barebone setup should be this:
<Style TargetType="{x:Type Expander}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="IsExpanded" Value="True" />
</Trigger>
</Style.Triggers>
</Style>
(Applies to the whole expander, not just the header. That would probably require messing with the template.)
It is possible to use databinding between isExpanded property an ismouseover:
IsExpanded="{Binding IsMouseOver, Mode=OneWay, RelativeSource={RelativeSource Self}}"

Changing Hyperlink foreground without losing hover color

I'm writing a WPF app, and I want some of my hyperlinks to be the default blue, and others to be green. No problem -- I can just set Foreground:
<TextBlock><Hyperlink Foreground="#0C0">Mark as done</Hyperlink></TextBlock>
The trouble is, when I do this, the hover effect goes away. In a normal Hyperlink, when I move the mouse over the link, it turns red, and when I move the mouse away, it goes back to blue. But in a Hyperlink with the Foreground property assigned, it's always that color -- the red-on-hover is totally suppressed.
How can I change a Hyperlink's color, without losing the default hover behavior and color?
Setting the Foreground directly (as you've done) doesn't work, and setting it in a Style doesn't work either, unless you "derive" that style from the default Hyperlink style (which must include the OnMouseOver trigger). So this works:
<TextBlock>
<Hyperlink>
<Hyperlink.Style>
<Style TargetType="Hyperlink"
BasedOn="{StaticResource {x:Type Hyperlink}}">
<Setter Property="Foreground" Value="#0C0"/>
</Style>
</Hyperlink.Style>
Mark as done
</Hyperlink>
</TextBlock>
Extracting that style back into the Window resources and referencing it with a key would probably make for more-readable XAML, but the above code does the job.
You should build your Hyperlink like this
<TextBlock Width="Auto" HorizontalAlignment="Center">
<Hyperlink Click="ForgotPassword_Clicked">
<TextBlock Text="Forgot Password?"/>
</Hyperlink>
</TextBlock>
And then this style should work for you
<Style TargetType="{x:Type Hyperlink}">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Foreground" Value="Blue" />
<Setter Property="TextBlock.TextDecorations" Value="{x:Null}" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Red" />
<Setter Property="TextBlock.TextDecorations" Value="Underline" />
</Trigger>
</Style.Triggers>
</Style>

Resources