Runtime binding change + unexpected event firing issue WPF - wpf

I change binding at runtime with datatriggers in XAML like this:
<ToggleButton Checked="MinSyncX_OnChecked" Unchecked="MinSyncX_OnUnchecked" TargetUpdated="FrameworkElement_OnTargetUpdated"
Tag="{Binding Path=CameraViewDirection, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
ToolTip="{Binding Source={StaticResource CameraLocalization}, Path=ToolTips.SyncX, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">
<ToggleButton.Style>
<Style TargetType="ToggleButton" BasedOn="{StaticResource CameraSyncCommonStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=CameraViewDirection.Limitations.UI.SelectedLimitation.W, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" Value="0">
<Setter Property="IsEnabled" Value="{Binding Path=CameraViewDirection.Limitations.UI.IsMinTripleEnabled.X, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"></Setter>
<Setter Property="IsChecked" Value="{Binding Path=CameraViewDirection.Limitations.UI.IsMinTripleChecked.X, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=CameraViewDirection.Limitations.UI.SelectedLimitation.W, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" Value="1">
<Setter Property="IsEnabled" Value="{Binding Path=CameraViewDirection.Limitations.UI.IsMaxTripleEnabled.X, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></Setter>
<Setter Property="IsChecked" Value="{Binding Path=CameraViewDirection.Limitations.UI.IsMaxTripleChecked.X, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=CameraViewDirection.Limitations.UI.SelectedLimitation.W, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" Value="2">
<Setter Property="IsEnabled" Value="{Binding Path=CameraViewDirection.Limitations.UI.IsBothTripleEnabled.X, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></Setter>
<Setter Property="IsChecked" Value="{Binding Path=CameraViewDirection.Limitations.UI.IsBothTripleChecked.X, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
<ToggleButton.Content>
<Image Source="{Binding Source={StaticResource CameraIcons}, Path=XAxis, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"></Image>
</ToggleButton.Content>
</ToggleButton>
Everything seems fine - binding really changes, but I have one issue which I don`t know how to solve:
When binding changed, MinSyncX_OnUnchecked event firing even if binded value is true which means that Toggle button must stays checked.
Firing of this event during binding switching braked my code, so I wish to now how to suppress this event during binding change if IsChecked property must be set to true.
A little tricky, but I hope you will understand my problem.
Edit
One thing I noticed that unchecked event ALWAYS fired if data trigger value switched to the first in list. Even it has a value=1 or value=2.
Does this by design or it can be fixed somehow?

I realise that I have twoway binding, so, when binding changed, my binded property receive value from button first (thats the reason why unchecked event firing). The solution I found is: lock logic of unchecked event by some bool value and switch that value back when binding changed (selection changed event on combobx in my case)

Related

Triggers override binding

Why is it that the binding Marked stops working when the triggers are used? Is there some way to fix this?
The multi selection ListBox has ListBoxItems with CheckBoxes, and the checkbox in an item is ticked when the corresponding item is selected, using mouse or keyboard or touch or whatever. The point with this demo is to not tick the checkboxes directly, but just multiselect the items and see the checkboxes get ticked as a consequence of that. This synchronization in the XAML works well, but since the Marked binding isn't working, the model won't get updated.
If I remove the triggers, then the binding Marked starts working. I know, because then the model gets updated when the checkboxes are ticked.
If I attach event handlers for Checked and Unchecked to the CheckBox, they fire even when the triggers are there.
<ListBox ItemsSource="{Binding Lines}" SelectionMode="Extended">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<CheckBox x:Name="cb"
Content="{Binding DisplayText}"
IsChecked="{Binding Marked, Mode=TwoWay}">
</CheckBox>
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" Value="true">
<Setter TargetName="cb" Property="IsChecked" Value="true"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" Value="false">
<Setter TargetName="cb" Property="IsChecked" Value="false"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
EDIT:
Although the accepted solution below is good XAML, it crashes with Elmish.WPF, which I'm using. That's another issue, and will be solved through other forums.
The DataTriggers will obviously override the Binding, since the ListBoxItem's IsSelected property is always either true or false.
Replace the DataTriggers by an ItemContainerStyle:
<ListBox ItemsSource="{Binding Lines}" SelectionMode="Extended">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding DisplayText}"
IsChecked="{Binding Marked}"/>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected" Value="{Binding Marked}"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>

WPF set default Visibility value when editing

I have Visibility bound to a bool, which works perfectly. However when editing the page the Border is not visible. I have to delete the Visibility Binding, make my changes and redo the Visibility Binding.
I'm pretty sure I saw there is a way to set a "editing default", but I cannot find that link anymore (or remember what it was called). Can someone explain how to set the default to visible so I can see it whilst editing, but not affect it's operation at runtime?
<Border Grid.Column="2" BorderBrush="HotPink" BorderThickness="2" MinHeight="100" MinWidth="100"
Visibility="{Binding ElementName=GenerateWorkOrders, Path=IsChecked, Converter={StaticResource booleanToVisibility}, UpdateSourceTrigger=PropertyChanged}">
<Label Content="Not Visible While Editing"/>
</Border>
The problem is that the default value of IsChecked of GenerateWorkOrders CheckBox is false
If IsChecked have Binding, you can use FallbackValue:
<CheckBox x:Name="GenerateWorkOrders" IsChecked="{Binding SomeProperty, FallbackValue=True}" />
Another way is to avoid the binding, you can use the DesignerProperties.IsInDesignMode Attached Properties that indicate if you in design mode (More inforamtion).
You can use this property in behavior, or in XAML only approach:
<Border Grid.Column="2" BorderBrush="HotPink" BorderThickness="2" MinHeight="100" MinWidth="100">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="Visibility" Value="{Binding ElementName=GenerateWorkOrders, Path=IsChecked, Converter={StaticResource booleanToVisibilityConverter}, UpdateSourceTrigger=PropertyChanged}" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=(componentModel:DesignerProperties.IsInDesignMode)}" Value="true">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Label Content="Not Visible While Editing"/>
</Border>

Switch ItemsSource dynamically in XAML

I'm trying to switch the itemssource of a treeview depending on a value of a property in my viewmodel. I've tried the code below and the trigger doesnt seem to be firing, can someone tell me where I went wrong?
<Window.Resources>
<Style x:Key="TreeViewItemSource" TargetType="TreeView">
<Style.Triggers>
<DataTrigger Binding="{Binding CurrentReportRequested, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Value="TollFree">
<Setter Property="ItemsSource" Value="{Binding InsertTFSQueryList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<TreeView ItemsSource="{Binding Source={StaticResource TreeViewItemSource}, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource DebugConverter}}" />
Set the ItemsSource in Style otherwise local set value will always holds priority.
Read more about it here - Dependency Property Value Precedence Order.
<Style x:Key="TreeViewItemSource" TargetType="TreeView">
<!-- Set ItemsSource here but you need to separate Style out of it. -->
<Setter Property="ItemsSource"
Value="{Binding Source={StaticResource TreeViewItemSource},
UpdateSourceTrigger=PropertyChanged,
Converter={StaticResource DebugConverter}}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding CurrentReportRequested, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
Value="TollFree">
<Setter Property="ItemsSource" Value="{Binding InsertTFSQueryList,
Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataTrigger>
</Style.Triggers>
</Style>
Most importantly you have set ItemsSource to the Style and somewhere in converter, you are converting it to actual value. This is the strangest thing I ever looked. How style is convertible to ItemsSource. Refactor the logic and separate out both so that above XAML works for you.
To solve my issue, I used good-old oop...polymorphism.
I used a polymorphic structure in my ViewModel. Now my ItemsSource is bound to one IEnumerable list which holds the base class...which i can equate to any of the derived types.

How can I localize the value of boolean groupheaders in RadGridView

I have a telerik WPF RadGridView in which I have localized most text strings, but when grouping on a boolean field, it shows true/false, I want to localize these values as well, but I can't figure out how. See image below for an illustration.
To localize the other strings, I am using a resx file with the keys found at http://www.telerik.com/help/wpf/gridview-localization2.html.
edit: I have also set the Language property of the user control to the appropriate locale
I managed to solve this with a rather nasty workaround, so I'm still looking for a better solution, but if anyone needs this for the future, I solved it like this:
<telerik:GridViewCheckBoxColumn Header="{Binding Resx.Confirmed}" DataMemberBinding="{Binding Confirmed}">
<telerik:GridViewCheckBoxColumn.GroupHeaderTemplate>
<DataTemplate>
<Label>
<Label.Style>
<Style TargetType="{x:Type Label}">
<Setter Property="Content" Value="{Binding DataContext.Resx.True, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Group.Items[0].Confirmed}" Value="False">
<Setter Property="Content" Value="{Binding DataContext.Resx.False, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
</DataTemplate>
</telerik:GridViewCheckBoxColumn.GroupHeaderTemplate>
</telerik:GridViewCheckBoxColumn>

WPF Xceed datagrid - datatrigger on cell's content makes me lose data on load...however re

I am using the Xceed datagrid for WPF. Today I was trying to change the background of the whole row if one of its column "SA" has the some value or not null. I wrote the following piece of code in XAML with a converter function in code behind:
<xcdg:DataGridControl.Resources>
<Style TargetType="{x:Type xcdg:DataRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource newConverter}, Path=Cells[SA].Content}" Value="True">
<Setter Property="Background" Value="LightGreen" />
</DataTrigger>
</Style.Triggers>
</Style>
</xcdg:DataGridControl.Resources>
To my surprise, as soon as I load the grid for the first time, the data in the SA column is nowhere to be seen. However, once I scroll down a bit, till the point that row which is supposed to have data for the column is not visible, and then when I scroll up again to see that row, I can see the value in that column as well as the background changed.
What am I doing wrong?
Use simple binding and avoid converter/template
<TextBlock Text="{Binding}"></TextBlock>
To fill color in your column use this or the following code:
<xcdg:Column Title="Unit Price" FieldName="UnitPrice" ReadOnly="True">
<xcdg:Column.CellContentTemplate>
<DataTemplate>
<DockPanel LastChildFill="false" x:Name="UnitPrice">
<TextBlock Text="{Binding}"></TextBlock>
<Image x:Name="img" Width="16" Height="16" DockPanel.Dock="Right"
Margin="2,0,0,0" Visibility="Collapsed"
ToolTip="Unit Price is Undefined." VerticalAlignment="Center"
HorizontalAlignment="Left" />
</DockPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding}" Value="0.00">
<Setter TargetName="img" Property="Visibility" Value="Visible" />
<Setter TargetName="UnitPrice" Property="Background" Value="Pink" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</xcdg:Column.CellContentTemplate>
</xcdg:Column>

Resources