WPF CheckBox multiBinding - c#

I need to bind a checkBox to TWO property and I think that i have to use multiBindings
so far i have this, but this doesn't work.
<CheckBox x:Name="FilterAll" Content="All">
<CheckBox.IsChecked>
<MultiBinding>
<Binding Path="SearchEngineCompassLogView.FilterSearch.IsFilterAllEnable"
Source="{StaticResource CompassLogView}">
</Binding>
<Binding Path="SearchEngineCompassLogView.FilterSearch.IsFilterVisible"
Source="{StaticResource CoreServiceLogView}">
</Binding>
</MultiBinding>
</CheckBox.IsChecked>
</CheckBox>
is this even possible with MultiBinding?

You could use MultiBinding. And as ethicallogics said, you must use a converter to do the actual logic of the parameters (whether you want to do AND, OR, whatever. You can see a little more about those here
I'm not sure what you are trying to affect on your checkbox, but in the end it will look something like this.
<CheckBox.IsChecked>
<MultiBinding Converter="{StaticResource MultiBoolConverter}">
<Binding Path="SearchEngineCompassLogView.FilterSearch.IsFilterAllEnable" Source="{StaticResource CompassLogView}"/>
<Binding Path="SearchEngineCompassLogView.FilterSearch.IsFilterVisible"
Source="{StaticResource CoreServiceLogView}"/>
</MultiBinding>
</CheckBox.IsChecked>
There is also another way to do this as well, which I sometimes find useful. It's called DataTriggers. If you've done any work with Styles and Templates then you may have seen them before. Here is an example based on your question:
<CheckBox>
<CheckBox.Style>
<Style TargetType={x:Type CheckBox}>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path="SearchEngineCompassLogView.FilterSearch.IsFilterAllEnable" Source="{StaticResource CompassLogView}" Value="True"/>
<Condition Binding="{Binding Path="SearchEngineCompassLogView.FilterSearch.IsFilterVisible" Source="{StaticResource CoreServiceLogView}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="CheckBox.IsChecked" Value="True"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>

You must specify converter in MultiBinding.Multibinding

Related

WPF Context Menu pops up after Binding changes

I have a Border control inside a UserControl which is used as a switch for graphical changes. The Border has a context menu with two MenuItems: "Open" and "Close".
When the switch is closed only the "Open" MenuItem is visible, and when the switch is open only "Close" is visible. For some switches I need to completely disable Open or Close, so I don't want them to be visible at any time. Here is the code:
<Border.ContextMenu>
<ContextMenu Name="switchContextMenu">
<ContextMenu.Visibility>
<MultiBinding Converter="{StaticResource ContextMenuBoolToVisibility}">
<Binding Path="OpenAvailable" />
<Binding Path="OpenVisible" />
<Binding Path="CloseAvailable" />
<Binding Path="CloseVisible" />
</MultiBinding>
</ContextMenu.Visibility>
<MenuItem Name="miOpen" Header="{Binding Path=Resources.PowerControlSystem_OPEN, Source={StaticResource LocalizedStrings} }"
Click="miOpen_Click">
<MenuItem.Visibility>
<MultiBinding Converter="{StaticResource BooleanToVisibilityMultiValueAND}">
<Binding Path="OpenAvailable" />
<Binding Path="OpenVisible" />
</MultiBinding>
</MenuItem.Visibility>
</MenuItem>
<MenuItem Name="miClose" Header="{Binding Path=Resources.PowerControlSystem_CLOSE, Source={StaticResource LocalizedStrings} }"
Click="miClose_Click">
<MenuItem.Visibility>
<MultiBinding Converter="{StaticResource BooleanToVisibilityMultiValueAND}">
<Binding Path="CloseAvailable" />
<Binding Path="CloseVisible" />
</MultiBinding>
</MenuItem.Visibility>
</MenuItem>
</ContextMenu>
</Border.ContextMenu>
I use this switch as a generic component, so inside another .xaml code I set the "Open Available" and "Close Available" properties. Here is my problem:
I have a switch with the Open Available property set to False. By default, this switch is open. I can closed it, and that's OK. Then when I right click on this switch again the context menu is not visible. This is also OK.
The problem is when I change some values this switch opens again, and at that point of time, the Context Menu pops up. I think that the problem is in the Converter for the ContextMenu visibility. It is triggered at this point and the ContextMenu becomes visible.
Does anyone have an idea how to stop this behavior?
Instead of setting the ContextMenu visibility, you can style the Border
<Border>
<Border.Style>
<Style TargetType="Border">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu Name="switchContextMenu">
<MenuItem Name="miOpen" Header="{Binding Path=Resources.PowerControlSystem_OPEN, Source={StaticResource LocalizedStrings} }"
Click="miOpen_Click">
<MenuItem.Visibility>
<MultiBinding Converter="{StaticResource BooleanToVisibilityMultiValueAND}">
<Binding Path="OpenAvailable" />
<Binding Path="OpenVisible" />
</MultiBinding>
</MenuItem.Visibility>
</MenuItem>
<MenuItem Name="miClose" Header="{Binding Path=Resources.PowerControlSystem_CLOSE, Source={StaticResource LocalizedStrings} }"
Click="miClose_Click">
<MenuItem.Visibility>
<MultiBinding Converter="{StaticResource BooleanToVisibilityMultiValueAND}">
<Binding Path="CloseAvailable" />
<Binding Path="CloseVisible" />
</MultiBinding>
</MenuItem.Visibility>
</MenuItem>
</ContextMenu>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Value="False">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource ContextMenuBoolAggregate}">
<Binding Path="OpenAvailable" />
<Binding Path="OpenVisible" />
<Binding Path="CloseAvailable" />
<Binding Path="CloseVisible" />
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="ContextMenu" Value="{x:Null}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
So the trigger is conditionally removing the ContextMenu instead of changing its visibility. I used the ContextMenuBoolAggregate converter name to indicate you need to create a new converter that is determining the correct value to remove the context menu - I think it's clear how to implement that part.
If your condition is simple enough, you can use MultiDataTrigger instead of DataTrigger with MultiBinding and Converter:
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding OpenAvailable}" Value="False"/>
<Condition Binding="{Binding OpenVisible}" Value="False"/>
<Condition Binding="{Binding CloseAvailable}" Value="False"/>
<Condition Binding="{Binding CloseVisible}" Value="False"/>
</MultiDataTrigger.Conditions>
<Setter Property="ContextMenu" Value="{x:Null}"/>
</MultiDataTrigger>
I found solution in another way. I used ContextMenuService.IsEnabled property. When is set to false, Context Menu can't be shown. So, I added this in my Border.xaml code:
<ContextMenuService.IsEnabled>
<MultiBinding Converter="{StaticResource ContextMenuBoolToVisibility}">
<Binding Path="OpenAvailable" ElementName="mySwitch" />
<Binding Path="OpenVisible" ElementName="mySwitch" />
<Binding Path="CloseAvailable" ElementName="mySwitch" />
<Binding Path="CloseVisible" ElementName="mySwitch" />
</MultiBinding>
</ContextMenuService.IsEnabled>
I also changed my ContextMenuBoolToVisibility converter. Instead of returning Visibility.Visible or Visibility.Collapsed, now returns true or false for ContextMenuService.IsEnabled property.

How to Pass multiple parameter in Multivalue Converter Over WPF DataTrigger

I'm having four int Property ProOne, ProTwo, ProThree and ProFour
I have to Implement the Boolean Logic ((ProOne == ProTwo) || (ProThree == ProFour)) in the Multivalue Converter namely VisibilityCheckConverter. Based on the Logic the Multivalue Converter VisibilityCheckConverter returns True or False.
Now I need to pass the four properties to the Converter over DataTrigger, Based on the Value, I have to change the Buttons Visibility to Visible
How does one write the a DataTrigger using Multivalue Converter with multiple parameters?
Sample Piece of XAML Code:
<ControlTemplate.Triggers>
<DataTrigger Property="{Binding , Converter={StaticResource VisibilityCheckConverter,ConverterParameter=ProOne ProTwo ProThree ProFour}}" Value="true">
<Setter TargetName="Button" Property="Visibility" Value="Visible" />
</DataTrigger>
</ControlTemplate.Triggers>
You can do something like this
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource VisibilityCheckConverter}">
<Binding Path="ProOne" />
<Binding Path="ProTwo" />
<Binding Path="ProThree" />
<Binding Path="ProFour" />
</MultiBinding>
</DataTrigger.Binding>
<Setter TargetName="Button" Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>

WPF DataGridTextColumn binding and style

here's the deal: styling the DataGridTextColumn's textblock for a datagrid.
I need to format the textblock by it's value, by comparing it from another binded value.
What i want to achieve is something like this:
<Style x:Key="ExpeditionerCellStyle" BasedOn="{StaticResource RightAlignStyle}" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=BEST}" Value="{RelativeSource Mode=Self}">
<Setter Property="Background" Value="Green" />
</DataTrigger>
</Style.Triggers>
</Style>
Which is not possible, because the Value of Datatrigger cannot be a relative source.
So i tried with multibinding
<Style x:Key="ExpeditionerCellStyle" BasedOn="{StaticResource RightAlignStyle}" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource IsValueEqualParameterConverter}">
<Binding Path="BEST" />
<Binding RelativeSource="{RelativeSource Mode=Self}" />
</MultiBinding>
</DataTrigger.Binding>
</DataTrigger>
</Style.Triggers>
</Style>
with no luck: textblock Text property is empty, probably because the style is applied before the actual binding is performed.
I have no more ideas.
Please help me!
I'm not sure if this will work, but I noticed that you forgot to specify the Binding.Path in your MultiConverter example... try this:
<Style x:Key="ExpeditionerCellStyle" BasedOn="{StaticResource RightAlignStyle}" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource IsValueEqualParameterConverter}">
<Binding Path="BEST" />
<Binding Path="Text" RelativeSource="{RelativeSource Mode=Self}" />
</MultiBinding>
</DataTrigger.Binding>
</DataTrigger>
</Style.Triggers>
</Style>
If you only want to change the style of the textblock based on the content of the textblock why not just add a bidning to the textblock background and use a converter to check the content of the text?
In other words bind both the text and the background to the same source and use a converter with the background and in the converter match the content and return the correct background style.
If you need something else leave a comment so we better know what the problem is.
I ended modifying a bit my code.
Instead of relying on the value of the cell, in the field "BEST" i passed the name of the column.
Then using the converter I check
Current textblock (as suggested by #Sheridan) -> DatagridCell -> Column's header
if it match, i change the style on this textblock.
Thanks everyone!!!

Change DataTrigger binding reference at runtime

I've a ListView with this DataTrigger attached:
<Style x:Key="HideShowStyle" TargetType="{x:Type ListViewItem}">
<Style.Resources>
<localConverters:ShowHideConverter x:Key="ShowHideConverter" />
</Style.Resources>
<Style.Triggers>
<DataTrigger Value="true">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource showHideConverter}">
<Binding Path="EndingDate" />
<Binding Path="UserName" />
<Binding ElementName="SearchBox" Path="Text" />
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
<DataTrigger Value="false">
(...)
</DataTrigger>
</Style.Triggers>
</Style>
I use this in a hardcoded scenario to hide/show some ListItems in the ListView. The binding source is specified in the ElementName tag, and the TextBox referred is declared a few lines before.
Now, I've the necessity to change that Binding at runtime with another field incapsulated in a istantiated class. I've tried to use WPF class instead of XAML, but nothing, I don't have any clue how to obtain this.
I'm open to any advice! :)
var style = (Style)FindResource("HideShowStyle");
var trigger = (DataTrigger)style.Triggers[0];
var multibinding = (MultiBinding)trigger.Binding;
var binding1 = (Binding)multibinding.Bindings[0];
var binding2 = (Binding)multibinding.Bindings[1];
var binding3 = (Binding)multibinding.Bindings[2];
Change bindings at will.

Value Converter not getting called when data changes

I'm working on a user control right now in which I have a path as part of the control. There are 3 possible paths I might want to display based on the values of certain data. To determine which Path I want to use, I have a value converter that takes in the data and returns a number to represent which of the paths I should use.
My first thought was to just use the property changed callback from the two dependency properties I am getting data from, but those callbacks must be static and the XAML code is always non-static.
My second attempt is to now use datatriggers with the value converter described above. Below is the code I have.
<Path x:Name="path" Stretch="Fill" Width="111.75" Height="118.718" Data="F1M205.917,103.0088C189.333,93.8108,170.128,88.9998,150,88.9998C129.873,88.9998,110.584,93.8108,94.167,102.8408L116.1,144.2508L150,208.7178L183.9,144.2508z" Canvas.Left="0" Canvas.Top="0">
<Path.Resources>
<Style TargetType="{x:Type Path}">
<Style.Triggers>
<DataTrigger Value="-1">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource ToleranceRangeTypeChecker}">
<Binding ElementName="UserControl" Path="ToleranceZoneLowerBound" />
<Binding ElementName="UserControl" Path="ToleranceZoneUpperBound" />
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Data" Value="F1M205.917,103.0088C189.333,93.8108,170.128,88.9998,150,88.9998C129.873,88.9998,110.584,93.8108,94.167,102.8408L116.1,144.2508L150,208.7178L183.9,144.2508z" />
<Setter Property="Width" Value="111.75" />
<Setter Property="Height" Value="118.718" />
<!--<Setter Property="Canvas.SetLeft"-->
</DataTrigger>
<DataTrigger Value="0">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource ToleranceRangeTypeChecker}">
<Binding ElementName="UserControl" Path="ToleranceZoneLowerBound" />
<Binding ElementName="UserControl" Path="ToleranceZoneUpperBound" />
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Data" Value="F1M150,88.9998C129.873,88.9998,110.584,93.8108,94.167,102.8408L150,208.7178C150,208.7178,150,114.157407529625,150,88.9998z" />
<Setter Property="Width" Value="55.917" />
<Setter Property="Height" Value="118.718" />
<!--<Setter Property="Canvas.SetLeft"-->
</DataTrigger>
<DataTrigger Value="1">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource ToleranceRangeTypeChecker}">
<Binding ElementName="UserControl" Path="ToleranceZoneLowerBound" />
<Binding ElementName="UserControl" Path="ToleranceZoneUpperBound" />
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Data" Value="F1M205.917,103.0088C189.333,93.8108 170.128,88.9998 150,88.9998 150,113.365662567029 150,208.7178 150,208.7178L183.9,144.2508z" />
<Setter Property="Width" Value="111.75" />
<Setter Property="Height" Value="118.718" />
<!--<Setter Property="Canvas.SetLeft"-->
</DataTrigger>
</Style.Triggers>
</Style>
Another thought I had was to instead actually have 3 different paths and use setters to change the visibility of each, but I think that having one path and changing it's propertise would be more logical. I would also prefer one path because my goal would be to eventually animate between the paths rather than have them change instantly.
Thanks!
You can get the instance by casting the sender parameter in the property change callbacks.

Categories