Calling an ElementMethod in a DataTrigger - wpf

I have a TextBox thats using this Style. I need to add a Focus() method to in this style.
So that when the TextBox is Visible and the ValidParent Property is false then i call the Focus() method on that TextBox
<Style x:Key="ParentTextBoxStyle" TargetType="{x:Type TextBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=ValidParent }" Value="false">
...
</DataTrigger>
<DataTrigger Binding="{Binding Path=ValidParent }" Value="false">
<Setter Property="BorderBrush" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
Is this possible ?? And if it is then if i had multiple textboxes with the same behaviour which one will recieve Focus?? Does the Order of the Controls in my Xaml make a diffrence then ??
Thank you

You cannot call methods via style triggers. Using Interactivity from the Blend SDK you have more options, including method calls but they cannot be easily used in styles.

Related

Style a custom WPF control when it's in a different state

I have a custom autocomplete control in WPF.It's created by combining a textbox and a dropdownlist, and a custom style for it.Looks like this ->"
The background color he has is the same even if is editable or readonly.And on my view i have more boxes and lists, they look like this ->
These are simple textboxes, and they change they're background depending on they're state: readonly or editable.
So my question is : how can i style my custom control to have that same gray background when it is in readonly mode in order to have the same standard on my view ?
I think you can use DataTrigger to get it works, like this:
<Style TargetType="YourCustomControl">
<Style.Triggers>
<DataTrigger Binding="{Binding IsReadOnly}" Value="True">
<Setter Property="Background" Value="ColorHere"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsReadOnly}" Value="False">
<Setter Property="Background" Value="ColorHere"/>
</DataTrigger>
</Style.Triggers>
</Style>

Why WPF Triggers must be declared into a style (even in-line)?

I don't understand why WPF allows me to write both
<Grid>
<Grid.Triggers>
<DataTrigger Binding="{Binding HasNeverBeenSeen}" Value="true">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Grid.Triggers>
</Grid>
and
<Grid>
<Grid.Style>
<Style TargetType="{x:Type Grid}">
<Style.Triggers>
<DataTrigger Binding="{Binding HasNeverBeenSeen}" Value="true">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid>
but only the second seems to work. Why is there a Triggers tag to Grid element if we must use a Style?
Thanks
Short answer to your question is because this is how it is designed by WPF team.
FrameworkElement.Triggers can only have EventTriggers although property is collection of TriggerBase. It's also clearly stated on MSDN page:
Note that the collection of triggers established on an element only
supports EventTrigger, not property triggers (Trigger). If you require
property triggers, you must place these within a style or template and
then assign that style or template to the element either directly
through the Style property, or indirectly through an implicit style
reference.

Trigger for IsChecked does not Trigger

I want to change the Icon of a ToggleButton (Content of Fluent RibbonBar) Depending on it's IsChecked Property. Now I have written the following style snippet:
<Fluent:ToggleButton.Style>
<Style BasedOn="{StaticResource RibbonButtonStyle}" TargetType="{x:Type Fluent:ToggleButton}">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Fluent:ToggleButton}}, Path=IsChecked}" Value="False">
<Setter Property="Icon" Value="{StaticResource ResourceKey=Style.Images.Pined}"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Fluent:ToggleButton}}, Path=IsChecked}" Value="True">
<Setter Property="Icon" Value="{StaticResource ResourceKey=Style.Images.Unpined}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Fluent:ToggleButton.Style>
The problem is that the Trigger doesn't load the Image well. The problem is not, that IsChecked doesn't actualize itself, I've already tested this. And also I don't set the icon property anywhere else. The image resources also works fine if I use them otherwhere.
Information for Rebuild: I've put the ToggleButton into the Backstage as the DataTemplate of a RibbonListBox placed in a BackstageTabItem.
Since this is a style for togglebutton you don't need a findancestor binding - you would use self. And actually since IsChecked is a DP you can just use a trigger - eg <Trigger Property="IsChecked" Value="False">
You absolutely need to remove the Icon property from the control declaration as it will override everything a style tries to do due to precedence.
But those DataTriggers will not work, the binding will look for an ancestor, itself excluded, so you must change them as well as already pointed out by AndrewS. Only if both conditions are met you have a chance of getting this to work (there may be even additional interferences though).

Style Trigger to Apply another Style

I am sure this has been asked before, but I haven't had an easy time figuring out how to phrase the query.
I have this style;
<SolidColorBrush x:Key="SemiTransparentRedBrushKey">#F0FF0000</SolidColorBrush>
<Style x:Key="TextBoxEmptyError" TargetType="{x:Type TextBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Text.Length}" Value="0">
<Setter Property="BorderBrush" Value="{StaticResource ResourceKey=SemiTransparentRedBrushKey}"/>
</DataTrigger>
</Style.Triggers>
</Style>
That I can apply to Textboxes to have a red border when they are empty. Its great, I can just add Style="{StaticResource TextBoxEmptyError}" to the Control Tag. But what if I want to apply this style with a trigger, so that the control only used it under certain conditions (like a binding being true)? Something like:
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=ApprovedRequired}" Value="True">
<Setter Property="Style" Value="{StaticResource TextBoxEmptyError}"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
This code throws an exception though {"Style object is not allowed to affect the Style property of the object to which it applies."}
Can something like this be done?
Edit: If this cannot be done with a Style trigger because it would overwrite itself, is there another way to Conditionally apply a resource style?
Edit: I can change the question title if there is a more proper term for this action.
Styles cannot be set from a Setter within the Style, because then essentially the first Style would never exist at all.
Since you're looking for a Validation style, I would recommend looking into Validation.ErrorTemplate, although if that doesn't work you can change your trigger so it modifies specific properties such as BorderBrush instead of the Style property
i would think of using a Template with a TemplateTrigger and there you can change the style to what ever you like based on what ever condition

Can I make a WPF DataGridRow unselectable?

I have a style on my datagrid to disable a DataGridRow based on a property binding. This makes the row unselectable, which is what I want. However, I am still able to select the disabled rows using at least 2 other ways. The first is if I use a dragging motion between two enabled rows that surround the disabled row. The second is if I click on the "select all" button on the top left of the datagrid. Is there a way to make specific rows completely unselectable?
This is what I currently have:
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding DisableMe}" Value="True">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
What about using the SelectionChanged event to undo the selection? I really don't think there is a straightforward way to it, anyway.
You could also change the row style so it appears unselected even if it IS selected, and filter it out the selection through code...
I just stumbled upon this thread with the same problem, and I want to point out that you can simply set enabled to false.
I don't think of any proper solution to this question. But as a workaround you can bind 'IsHitTestVisible' property of DataGrid to 'IsEnabled'.
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Setter Property="IsEnabled" Value="True" />
<Setter Property="IsHitTestVisible" Value="{Binding RelativeSource={RelativeSource Self},Path=IsEnabled}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding DisableMe}" Value="True">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>

Resources