WPF: Problem with Checkbox when binding datatrigger to property "Ischecked" - wpf

I have a checkbox in GridViewColumn which i use for show/change database value. The click event for the checkbox is used for change value in the database. For handling the state of property "IsChecked" I'm using datatrigger and a setter, se xaml code below:
<Style TargetType="CheckBox">
<Setter Property="IsEnabled" Value="True" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=ID, Converter={StaticResource Converter}}" Value="true">
<Setter Property="IsChecked" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
The binding works great until I click the checkbox. After I clicked the checkbox for the first time the state of the property "IsChecked" don't updates if a manually in the Database change the value which i mapped to the property "IsChecked".
If I map for example the same value to the property "Content" of the checkbox the trigger works fine even after I've clicked the checkbox.
Does anyone no whats the problem is?

Shouldn't
<Style TargetType="CheckBox">
instead be:
<Style TargetType="{x:Type CheckBox}">
Edit:
you could try this:
<Style TargetType="{x:Type CheckBox}" >
<Setter Property="IsChecked" Value="{Binding Path=ID, Converter={StaticResource Converter}}" />
</Style>

You can try to add a second data trigger to set the checkbox to false. As I can see from your code you set the IsChecked only to true, but never to false.

In stead of using Click to determine the changes, perhaps you can use the Checked and Unchecked events ?

Related

How to set a viewmodel property if a listbox item selected?

I have a listbox...and it is bound to list of items of type (class) "A". Class "A" has a boolean property "IsCurrentViewActive". This is false by default. When user select an item in listbox....i need to set the "IsCurrentViewActive" property of corresponding item to TRUE.
I tried the below code in my listbox...but it is not working..Any help would be appreciated.
<Style x:Key="ListBoxItemTabStyle2Extended" TargetType="{x:Type ListBoxItem}" >
<Setter Property="IsSelected" Value="{Binding Path=IsCurrentViewActive, Mode=TwoWay}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}" Value="True">
<Setter Property="IsSelected" Value="{Binding Path=IsCurrentViewActive, Mode=TwoWay}"/>
</DataTrigger>
</Style.Triggers>
</Style>
EDIT : Can we do this way or Do I need to use attached property ?
The above XAML worked fine for me actually. I think it's just a matter of getting the context right. I have created a sample that you can download where this works fine. I think the difference might be that in my version, I store the style in ListBox's parent control's resources. I don't think you can store them in the ListBox's resources.
https://www.dropbox.com/s/s64kp9p0b2w1imk/ListBoxMenu.7z?dl=0

Binding to the Items properties of an ItemsControl

I'm looking to a way to bind a Button Text or IsEnabled property for example to the IsChecked property in an ItemsControl
Here is my simplified source code :
<StackPanel>
<ItemsControl ItemsSource="{Binding Tasks}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="10,0,10,0" Text="{Binding Name}"/>
<CheckBox IsChecked="{Binding InProgress}"/>
<CheckBox IsChecked="{Binding Done}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Button/>
</StackPanel>
I would like (for example) if all the "Done" CheckBoxes are Checked, to set Button Text to some value or to enable it. I thought doing this with Data Binding in Xaml using DataTriggers but I don't know how to do it.
Ca anyone give me a full xaml solution ?
New Answer
Sorry, I misunderstood the question. I would expose another property from your DataContext that simply returns true/false if all the items in the collection are checked or not, and base your Button's Text/IsEnabled off that property using a DataTrigger
<Style TargetType="{x:Type Button}">
<Setter Property="IsEnabled" Value="False" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsAllChecked}" Value="True">
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
Old Answer
DataTriggers simply take a binding, and check if the result is equal to some value.
<Style TargetType="{x:Type TextBox}">
<Setter Property="IsEnabled" Value="False" />
<Style.Triggers>
<DataTrigger Binding="{Binding Done}" Value="True">
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
If you need to test more than one condition, you need a MultiDataTrigger
<Style TargetType="{x:Type TextBox}">
<Setter Property="IsEnabled" Value="False" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=InProgress}" Value="True" />
<Condition Binding="{Binding Path=Done}" Value="True" />
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="True" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
Note that the default value of setter is part of the style. This is important because if you set the default value on the <TextBox> then it has a higher priority than triggered values, so triggered values are unable to change the current value.
You can change this line...
<Button/>
To this
<Button Content={Binding ButtonContent}/>
And set the 'ButtonContent' property in your ViewModel whenever your 'Done' check box gets checked.
Usually, the best way to do that is to synthesize the state you want to apply to your button into a property of your ViewModel.
The WPFy way in that case is for your ViewModel to expose a command that implements the action of your button.
The command in turns can react to changes in your data to signal if it is available or not, and thus will automaticaally disable/enable your button. An added bonus is that you can easily implement a menu for example, that will be properly enabled/disabled at no cost once you have your command.
It's been a long time since I had any chance to touch WPF, so I do not have any really useful links at hand, but if I were you I would learn about commands in WPF, they are a very important part of the MVVM architecture.

How Biniding Mode(TwoWay) works?

I was trying out some dummy application just to test binding modes. So, just curious to know how did the binding modes work. I have this xaml code-
<Button x:Name="btn"
Height="20"
Width="200"
VerticalAlignment="Top">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="IsEnabled"
Value="{Binding CanEnable, Mode=TwoWay}" />
<Style.Triggers>
<DataTrigger Binding="{Binding TextChanged}" Value="true">
<Setter Property="IsEnabled"
Value="true" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Here by button IsEanbled is binded to my viemodel property "CanEanble" whose default value is false. Now in my trigger i was listening to "TextChanged" property and setting button IsEnabled to true. Button gets enabled as it should be but the property "CanEnable" did not set to true even the biding mode is set to TwoWay..
Why this is happening??
By setting the value in the trigger you basically remove the binding you previously set in the style setter. Take a closer look at the style. You will notice that you basically you set the property IsEnabled twice. First in the style setter, second in the trigger. It is logical that the second value overrides the previous value.
The desired effect can be achieved from code if you set the value of the dependency property using SetCurrentValue method:
SetCurrentValue(Button.IsEnabledProperty, true);
This way the bindings set on this property will not be removed and it will work as expected.

DataTrigger does not work as expected

I have a ComboBox bound to a ViewModel property called Property.
Property is a TypeDescriptor.
When user changes the value in the ComboBox, the Property is updated.
On the UI i would like to either hide or make visible different controls: textbox, combobox, date picker etc.
Problem is, the DataTrigger is not working as expected.
<Style x:Key="textboxStyle"
TargetType="{x:Type TextBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Property.PropertyType}"
Value="{x:Type Type={x:Type sys:String}}">
<Setter Property="Visibility"
Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
You might need to write a Converter which gets invoked when the value of 'Property' changes. The converter can be a 'TypeDescriptior to Visibility converter.
The reason why the above doesnt work is because 'PropertyType' doesnt trigger INotifyPropertyChanged.

WPF ComboBox - showing something different when no items are bound

I have a ComboBox, and i want to change its look when the ItemsSource property is null. When it is in that state, i want to show a TextPanel with the text "Retrieving data" in it, and give it a look kind of similar to the watermarked textbox.
I figure to do this i need a ControlTemplate, and a trigger. I have the ControlTemplate here:
<ControlTemplate x:Key="LoadingComboTemplate" TargetType="{x:Type ComboBox}">
<Grid>
<TextBlock x:Name="textBlock" Opacity="0.345" Text="Retrieving data..." Visibility="Hidden" />
</Grid>
<!--
<ControlTemplate.Triggers>
<Trigger Property="ComboBox.ItemsSource" Value="0">
<Setter Property="Visibility" Value="Visible" />
</Trigger>
</ControlTemplate.Triggers>
-->
</ControlTemplate>
but my issue is how do i set up the trigger to show this when the ItemsSource property is null? I have tried a couple of different ways, and each way has given me the error message "Value 'ItemsSource' cannot be assigned to property 'Property'. Invalid PropertyDescriptor value.". My ComboBox xaml is this (including the attempted trigger):
<ComboBox Margin="112,35,80,0"
Name="MyComboBox"
Height="22.723"
VerticalAlignment="Top"
DisplayMemberPath="FriendlyName"
SelectedValuePath="Path"
TabIndex="160"
>
<Trigger>
<Condition Property="ItemsSource" Value="0" />
<Setter Property="Template" Value="{StaticResource LoadingComboTemplate}" />
</Trigger>
</ComboBox>
now should the trigger go on the ComboBox, or on the ControlTemplate? How do i access the ComboBox's ItemsSource property? Should i even be using a trigger?
Thanks!
Try putting {x:Null} for the value of the condition instead of 0.
Also I got it working by moving the Trigger to a style and modifing it slightly, see below.
<Style TargetType="ComboBox" x:Key="LoadingComboStyle">
<Style.Triggers>
<Trigger Property="ItemsSource" Value="{x:Null}">
<Setter Property="Template" Value="{StaticResource LoadingComboTemplate}" />
</Trigger>
</Style.Triggers>
</Style>
<ComboBox Style="{StaticResource LoadingComboStyle}" .... >
The reason it only works in a style, is that only EventTriggers are allowed in the triggers collection directly on the Framework Element. For property triggers (like above) you need to use a style (I learn something every day).
See FrameworkElement.Triggers
Note that the collection of triggers established on an element only supports EventTrigger, not property triggers (Trigger). If you require property triggers, you must place these within a style or template and then assign that style or template to the element either directly through the Style property, or indirectly through an implicit style reference.

Resources