WPF: Conditionally put focus on checkbox and button - c#

I want to set focus on conditionally in a WPFform. Here I have two types of control. One is 'checkbox' and other one is button. The checkboxes are getting enabled on some condition, however the button control(s) are visible by default. I am able to put focus on button(s) whether checkboxes are getting enabled or not. Though checkboxes should get focus over button when checkboxes are getting enabled. Kindly, suggest an approach to achieve this please. I have used following code to achieve focus on button(s)
<Style x:Key="FocusElement" TargetType="Grid">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=chkCA, Path=IsVisible}" Value="True">
<Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=chkCA}"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=btnSaveAll, Path=IsVisible}" Value="True">
<Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=btnSaveAll}"/>
</DataTrigger>
</Style.Triggers>
</Style>
Thanks!

Related

Bind visibility of a control to combobox selection

I have a combobox which is bound to an Enum datatype. Right now the combobox binding works fine but when I tried to bind the visibility of a checkbox to the combobox selection, this binding is not working as expected. What I wanted to do was whenever the combobox selection is "Restore", I want a checkbox to be visible. Below is the code that I am using.
<CheckBox.Style>
<Style TargetType="CheckBox">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=cmbOperation, Path=SelectedValue}" Value="Restore">
<Setter Property="Visibility" Value="Visible"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
I tried changing the Path between SelectedValue, SelectedItem , SelectedValue.TosString() (hopelessly) but I am not getting the checkbox to change its visibility whenever the combobox has "Restore" as its selection. Should I be making any changes in the Enum that I am binding to the Combobox ? If not, what else am I doing wrong?
I'm willing to bet that you've set Visibility on the CheckBox in the XAML:
<CheckBox
Visibility="Collapsed"
>
However, due to the rules of Dependency Property Value Precedence in WPF, that will override anything that happens in the Style. This is by design and it's not a bad idea when you think through all the implications, but it bites everybody who's new to WPF.
It's an easy fix: Just set the starting value in a Setter in the Style. What the Style does, the Style can undo.
<CheckBox
>
<CheckBox.Style>
<Style TargetType="CheckBox">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=cmbOperation, Path=SelectedValue}" Value="Restore">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>

Set Background of button based on Content or CustomDP value

I have a button whose Content property keeps changing based on certain conditions which are set from the ViewModel. Essentially it gets set a value from 0 to 1000.
I also have another custom DP property on the same button whose value can be set to a certain enum.
What I am trying to solve is as follows (and unfortunately have no idea how I should go about it):
If my button content value is 0 - background of the button should be Gray.
If my button content value is 1 - background of the button should be Yellow.
If my button content value is 1 & the Custom DP has a value set (not the default value) - background should change to Red.
If my problem statement was just dealing with setting a background based on the integer set on the content - I could easily use Converters (String to Brush) and set my background. But the last condition which is now setting my background based on custom DP value coming in - have no idea how to solve...
Can somebody please suggest me an approach - sample code to solve such a problem.
<Button Content="0">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self},Path=Content}" Value="0">
<Setter Property="Background" Value="Gray"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self},Path=Content}" Value="1">
<Setter Property="Background" Value="Yellow"/>
</DataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=Content}" Value="1"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=YourDP}" Value="YourValue"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Background" Value="Red"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
You can use multi-conditions triggers or multi data triggers. See this link and this link.

Collapse details in listbox by clicking a button

I'm trying do make something like this: when you click the button, the listboxitem collapses and shows some additional information:
I have already made something similar: details are showed when the whole item item is clicked.
Any ideas how to modify this style so collapsing will take place only if the button (or near it) is clicked?
Code:
<Style x:Key="collapsingGridStyle" TargetType="{x:Type Grid}">
<Style.Triggers>
<DataTrigger
Binding="{Binding
Path=IsSelected,
RelativeSource=
{
RelativeSource
Mode=FindAncestor,
AncestorType={x:Type ListBoxItem}
}
}"
Value="False">
<Setter Property="Grid.Visibility"
Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
There are many ways how can you achieve this behavior. For example, you can use expander in listboxitem template.

Trigger on ContextMenu.IsOpen in XAML

Here's what I'm trying to do:
<Style x:Key="TreeViewItemStyle">
<Setter Property="TreeViewItem.ContextMenu" Value="{StaticResource ContextMenu}" />
<Style.Triggers>
<Trigger Property="TreeViewItem.ContextMenu.IsOpen" Value="True">
<Setter Property="TreeViewItem.BitmapEffect">
<Setter.Value>
<OuterGlowBitmapEffect GlowColor="Yellow" GlowSize="2"/>
</Setter.Value>
</Setter>
</Trigger>
</Style>
...
But it is obviously not working because Property="TreeViewItem.ContextMenu.IsOpen" is not recognized. Any suggestions to what I need to change?
You can bind to the IsOpened property of the context menu using a DataTrigger:
<DataTrigger Binding="{Binding ContextMenu.IsOpen, RelativeSource={RelativeSource Self}}" Value="True">
<Setter Property="Background" Value="Green"/>
</DataTrigger>
Unfortunately, since all of the items in TreeView share the same ContextMenu, that will highlight all of them at once. There doesn't seem to be a property that lets you find out which FrameworkElement opened the ContextMenu.
You could handle the ContextMenuOpening and ContextMenuClosing events on the TreeViewItem, since those will bubble up from the control that handled the click and pass through the right TreeViewItem. If you want to do it in XAML, you could use an EventTrigger to start a one-frame animation that changes your property. The cleanest option may be to write an attached behavior that handles the ContextMenuOpening and ContextMenuClosing events and sets an attached property to true when the context menu is open.

Applying a DataTrigger to a Button Whose Binding Comes From Another Control?

I'm trying to apply a DataTrigger to a Button and it depends on a property from the currently selected item of a TreeView. The idea is that I want to change the text of a Button depending on a property of the selected item.
What I have looks like this:
<Button x:Name="m_AddObject" Margin="192.708,0.909,6,6.363" Click="AddObject_Click" >
<DataTrigger Binding="{Binding ElementName=ObjectTreeView, Path=SelectedItem.Removable}" Value="true">
<Setter TargetName="m_AddObject" Property="Content" Value="Remove" />
</DataTrigger>
</Button>
But I can't get it to compile. The Setter complains about "Content" not being valid because it doesn't have a qualifying type name, but if I change it to "Button.Content" it then complains of "Object reference not set to an instance of an object".
I also tried:
<Setter TargetName="m_AddObject.Content" Value="Remove" />
While that compiles, it didn't work either.
I'm stumped.
Any ideas?
Thanks!
DataTriggers should be defined in a Style for the button. What you're trying to do above is essentially use a DataTriggers as the "label" (the "Content", as WPF puts it) for the button (instead of, say, "OK").
This is ad-hoc, so it might not be totally correct, but it's closer to what you want:
<Button x:Name="m_AddObject"
Margin="192.708,0.909,6,6.363"
Click="AddObject_Click">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ObjectTreeView, Path=SelectedItem.Removable}" Value="True">
<Setter Property="Content" Value="Remove" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>

Categories