WPF Converter with triggers - c#

i have this XAML that looks to see if a row can be
enabled or not inside a DataGrid
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding State, Converter={StaticResource converter}}" Value="true">
<Setter Property="IsEnabled" Value="true"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
The converter is working and returns false or true, however when it sends back false, the row is still enabled, have I done anything wrong here?

The default value for IsEnabled is true. So it will always be true unless you specify in a trigger for it to be false.
You should do the following:
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding State, Converter={StaticResource converter}}" Value="False">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
Therefore, it'll stay true by default and switch to false only when this trigger is activated.

Related

Wpf mahapps collapse datagrid row by condition not working

I need to hide rows under a certain condition, I do this through a style trigger. But for some reason it doesn't work if you use Map apps styles. If I delete styles from the dictionary, everything works. What i need to do to make it work with Mah app styles as well?
<DataGrid.ItemContainerStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsArchive}" Value="True">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.ItemContainerStyle>
I also tried using baseOn but it still doesn't work
Set the RowStyle instead of ItemContainerStyle:
<DataGrid.RowStyle>
<Style TargetType="DataGridRow" BasedOn="{StaticResource MahApps.Styles.DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsArchive}" Value="True">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>

Window.Visibility won't update through trigger

I'm trying to set a trigger to hide my window whenever a property in my ViewModel changes. I tried using the same trigger on a different element and that worked exactly as expected, so it appears that I cannot change the visibility property of a window using a trigger. Are there any workarounds I can use to hide my window?
<Window.Style>
<Style TargetType="Window" BasedOn="{StaticResource Shell}">
<Setter Property="Visibility" Value="Hidden"/>
<Setter Property="Left" Value="{Binding SecondDisplayLeftSide}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ShellType}" Value="InstructorMultiDisplay">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Style>

DataTrigger setter will not update property. Why?

XAML :
<RadioButton x:Name="RadioButtonA">
<RadioButton.Style>
<Style TargetType="RadioButton">
<Setter Property="IsChecked" Value="{Binding Path=RadioAValue}" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=CheckBoxA, Path=IsChecked}" Value="True">
<Setter Property="IsChecked" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</RadioButton.Style>
</RadioButton>
C# Code behind
public bool RadioAValue
{
get
{
...
}
set
{
...
}
}
set section of RadioAvalue will not be called when CheckBoxA is checked.
Any reason why?
Problem in your code
You are setting the binding in Style Setter
<Setter Property="IsChecked" Value="{Binding Path=RadioAValue}" />
and on clicking the checkbox you have overwriting the Binding with the value False. Now there is no more Bindings over the element and it wont call the set anymore.
Also, if you try to bind it over the RadioButton itself instead of setters that will take more precedence and your Triggers won't work there.
Solution
I would recommend you to have Command binding over the Checkbox and update the value RadioAValue from your ViewModel
If you want conditional setter use MultiBinding, right now you block binding with already setted value
<Setter Property="IsChecked" Value="{Binding Path=RadioAValue}" />
Must be something like this (didn't test thought):
<RadioButton x:Name="YouRadioButton">
<RadioButton.Style>
<Style TargetType="RadioButton">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=CheckBoxA, Path=IsChecked}" Value="True"/>
<Condition Binding="{Binding RadioAValue}" Value="True"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="IsChecked" Value="True"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
<DataTrigger Binding="{Binding ElementName=CheckBoxA, Path=IsChecked}" Value="False">
<Setter Property="IsChecked" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</RadioButton.Style>
</RadioButton>
<CheckBox x:Name="CheckBoxA"/>

WPF databinding to interface cannot find property

I am working from the solution presented here, which has worked well for me until this point. I'm now trying to perform datatrigger binding to an interface property via the following XAML:
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(selection:IChartDefinitionViewModel.SelectedItem).HasErrors}" Value="False">
<Setter Property="Background" Value="Transparent"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=(selection:IChartDefinitionViewModel.SelectedItem).HasErrors}" Value="True">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
When I enter this code I get a warning "The member 'SelectedItem' is not recognized or is not accessible", and I get a similar exception when I try to run. Only thing is, there is a member SelectedItem defined on the interface, and I can even navigate to it from the XAML:
public interface IChartDefinitionViewModel : IReactiveSelector<SomeClass>, IMayHaveErrors
{
// stuff
}
public interface IReactiveSelector<T> : // more stuff
{
T SelectedItem { get; set; }
}
Can anyone advise why this is happening and what I can do for a workaround? I'd like to manage this based on the interface definition or using a datatemplate for my IChartDefinitionViewModel implementation, if possible.
Update:
This also does not work, but for a different reason - when I attempt to bind to the object directly, the background doesn't change despite the fact that HasErrors toggles from true to false.
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedItem.HasErrors}" Value="True">
<Setter Property="Background" Value="Transparent"/>
</DataTrigger>
<DataTrigger Binding="{Binding SelectedItem.HasErrors}" Value="False">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
There appear to have been two issues with my original post. The first is that there was a datacontext issue - thanks to James Durda for pointing this out. The row context is of type ChartDefinitionViewModel, so this code works as desired:
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(selection:ChartDefinitionViewModel.HasErrors)}" Value="False">
<Setter Property="Background" Value="Transparent"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=(selection:ChartDefinitionViewModel.HasErrors)}" Value="True">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
Interestingly, however, binding to the HasErrors property on the IChartDefinitionViewModel interface results in a thrown exception stating that the property path is invalid, which brings me back again to my original inquiry:
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(selection:IChartDefinitionViewModel.HasErrors)}" Value="False">
<Setter Property="Background" Value="Transparent"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=(selection:IChartDefinitionViewModel.HasErrors)}" Value="True">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
Things, however, begin to work as expected when I bind to the interface on which the HasErrors property is directly defined.
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(interfaces:IMayHaveErrors.HasErrors)}" Value="False">
<Setter Property="Background" Value="Transparent"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=(interfaces:IMayHaveErrors.HasErrors)}" Value="True">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
I'm not sure if this is an isolated case, but it appears that WPF binding can't locate properties defined upwards in the interface inheritance hierarchy, at least in this instance.

One setting is determined by the second settings

I have the same options in different WPF dialog. One option that depends on another. If I click on the first, I also want to check the second. Both options correspond to the private bool variable in different classes. What is the best solution for this problem?
You could do that in WPF/XAML with Style.Triggers. For example the following code is an example on how to bind a textblock control's IsEnabled status based on the status of a checkbox (checked/unchecked)
<TextBlock Text="mytextblockText: ">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked,ElementName=myCheckbox}" Value="False">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsChecked, ElementName=myCheckbox}" Value="True">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
For a checkbox being checked when another checkbox is checked, it looks like this (I guess)
<CheckBox>
<CheckBox.Style>
<Style TargetType="CheckBox">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked,ElementName=myCheckbox}" Value="False">
<Setter Property="IsChecked" Value="True"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsChecked, ElementName=myCheckbox}" Value="True">
<Setter Property="IsChecked" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
*edit
can the properties in the classes be changed by something different than by those checkboxes? If yes, you could fire an event when the property is changed or directly manipulate the checkstate of the according box. Also, are the boxes dependent on each other? Or is just one dependent on the other (A <=> B or A => B)?
For manipulating the properties when one of the boxe's state is changed you could use the Checked/Unchecked events. Or use DependencyProperty as described in Pat's answere over here

Categories