MultiDataTrigger not working with binding path condition - c#

I have implemented a WPF user control and what i want to achieve here is on mouseover on Main Grid some stack panels should hide. And i need to have multiple triggers conditions. Despite looking everywhere i am unable to find what am i doing wrong. UserControl Resources are as follow
<UserControl.Resources>
<Style x:Key="StackViewStyle" TargetType="{x:Type StackPanel}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource AncestorType=Grid},Path=IsMouseOver}" Value="True" />
<Condition Binding="{Binding Path=FileState, RelativeSource={RelativeSource Self}}" Value="Uploading" />
</MultiDataTrigger.Conditions>
<Setter Property="Visibility" Value="Collapsed"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
Data binding is working fine, because when i put in a test label to check its value it was "uploading". If i remove FileState Condition it starts working. I am using it as
<StackPanel Name="StackViewCount" Style="{StaticResource StackViewStyle}">
...
</StackPanel>
While looking output window i found this error
BindingExpression path error: 'FileState' property not found on 'object' ''StackPanel' (Name='StackViewCount')'. BindingExpression:Path=FileState; DataItem='StackPanel' (Name='StackViewCount'); target element is 'StackPanel' (Name='StackViewCount'); target property is 'NoTarget' (type 'Object')
So how can i tell the binding to look for FileState in UserControl not stackpanel
Now when i changed condition to
<Condition Binding="{Binding Path=FileState}" Value="Uploading" />
I dont see any errors but still it does not work.

Since FileState is property of your UserControl and it is ancestor of StackPanel you have to bind to ancestor like:
<Condition Binding="{Binding Path=FileState, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" Value="Uploading" />

Related

XAML binding from 2 XAML objects -Xamarin

I want to set property IsEnabled of button based on switch and picker using binding. Something like this:
XAML:
<Button Text="Start tracking"
AbsoluteLayout.LayoutBounds="0, 1, 1, 0.1"
AbsoluteLayout.LayoutFlags="All"
x:Name="startTrackingButton"
IsEnabled="{Binding}"
Clicked="StartTracking_Clicked"
VerticalOptions="CenterAndExpand"/>
Code behind:
startTrackingButton.BindingContext = (!autoTrackingSwitch.IsToggled || frequencyPicker.IsSet);
This solution does not work. How can I do it? Thank you.
Try using Style:
<Style TargetType="Button">
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<BindingCondition Binding="{Binding Source={x:Reference autoTrackingSwitch}, Path=IsToggled}" Value="True"/>
<BindingCondition Binding="{Binding Source={x:Reference frequencyPicker}, Path=IsSet}" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Enabled" Value="True"/>
</MultiTrigger>
</Style.Triggers>
</Style>
You can specify it inside Button.Resources of your button.

How to enable or disable the checkbox based on property value?

In my DataGrid I've a DataGridCheckBoxColumn implementation:
<DataGrid ItemsSource="{Binding Collection}">
<DataGrid.Columns>
<DataGridCheckBoxColumn Binding="{Binding Selected}"
ElementStyle="{StaticResource MaterialDesignDataGridCheckBoxColumnStyle}"
EditingElementStyle="{StaticResource MaterialDesignDataGridCheckBoxColumnEditingStyle}">
<DataGridCheckBoxColumn.CellStyle>
<Style TargetType="DataGridCell">
<EventSetter Event="CheckBox.Unchecked" Handler="Match_Unchecked"/>
<Style.Triggers>
<!-- Enabling -->
<DataTrigger Binding="{Binding DataContext.IsAdding,
RelativeSource={RelativeSource AncestorType=Window}}" Value="false">
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
<!-- Disabling -->
<DataTrigger Binding="{Binding DataContext.IsAdding,
RelativeSource={RelativeSource AncestorType=Window}}" Value="True">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style>
</DataGridCheckBoxColumn.CellStyle>
as you can see I've inserted a DataTrigger on the Style of DataGridCheckBoxColumn, so essentially when the property IsAdding is false, the Cell with the content inside should be enabled, otherwise, disabled.
This doesn't seems to working, the Cell is even enabled, why?
I suspect the problem is with the LogicalTree of your application. The code you have there should actually work just fine, but it appears that you may be testing this inside of the demo application. Normally this would be fine, however there was an addition of a control to display XAML that is breaking the logical tree (I have a fix in progress but it is not complete yet).
You can work around this by making two changes to the demo application:
In the MainWindow.xaml replace the XamlDisplayerHost with a regular ContentControl
In Grids.xaml replace the XamlDisplayerPanel with a regular StackPanel
After that your style should work as you expect.

Automatically refresh ListView from a checkbox

I have a ListView that's bound to a simple array of objects (mainly getters / setters). It shows after the main code has run as a simple report. Initially the dialog just shows the items that changes. I have "Show All Details" checkbox that the user can check to see all items. I have a MultiTriggger setup on the checkbox and the "ZeroChanged" property. The issue seems to be that the ListView needs to be told to refresh when the checkbox changes state so that the MultiTrigger will then adjust the Visibility Value = "Collapsed" action. I'm starting to think that I'll need some supporting C# code to process the checkbox and then refresh the ListView. The array of objects doesn't change, it's fixed output from the main program. The check box defaults to false Is this possible with just XAML?
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=_showAllDetailsChkBox}" Value="False" />
<Condition Binding="{Binding ZeroChanged}" Value="True" />
</MultiDataTrigger.Conditions>
<Setter Property="Visibility" Value="Collapsed" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
If you bind to the IsChecked property of the CheckBox, the Visibility property of the ListView should get set as soon as you check or uncheck the CheckBox. You are missing a binding path:
<Condition Binding="{Binding Path=IsChecked, ElementName=_showAllDetailsChkBox}" Value="False" />
<Condition Binding="{Binding ZeroChanged}" Value="True" />

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.

Datagrid multitrigger referencing values from code-behind

I'm still bloody green in WPF and have not yet fully grasped the concept behind it. I've got the following problem:
I want to set triggers in a datagrid depending on a precondition.
Example:
In my code-behind, I have a string variable, let's call it variableString. Now depending on the the value of variableString, I want to enable/disable the triggers inside a datagrid, that I have defined in XAML like:
if(variableString == "a")
then
XAML
<DataGrid AutoGenerateColumns="False" Margin="5,5,0,75" Name="dataGrid1" ItemsSource="Binding}">
<DataGrid.ItemContainerStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=SomeColumnName}" Value="someValue">
<Setter Property="Background" Value="White"/>
<DataTrigger Binding="{Binding Path=SomeColumName}" Value="someOtherValue">
<Setter Property="Background" Value="Red"/>
</Style.Triggers>
</Style>
</DataGrid.ItemContainerStyle>
Otherwise, if
if(variableString == "b")
then
Do Nothing`
I've already tried binding the string to the datacontext of the datagrid, but that was rather contra-productive, as it removes my binding to the database.
Can anyone help me here. An example, a push in the right direction etc...
I really like the options that WPF gives you, however it's that fundamental things, that were so easy to handle in WinForms, that drive me mad in WPF.
Thanks
I think you want a MultiDataTrigger, which allows you to base your trigger off of multiple values
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=SomeColumnName}" Value="someValue" />
<Condition Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=variableString}" Value="A" />
</MultiDataTrigger.Conditions>
<Setter Property="Background" Value="White" />
</MultiDataTrigger>
To find your string in the code behind, you'll probably have to use some kind of RelativeSource binding to find the class containing that property. My example assumes there is a public property called variableString on the Window class

Categories