Select All Checkbox in XAML using trigger? - wpf

I'd like to implement a select all checkbox in xaml.
I have several (templated) checkboxes in a listview. Then I have a checkbox outside of the listview, which I want to have a "select all"-behaviour.
I could easily solve the problem in my ViewModel, however, I think it would be more elegant to do this in xaml, since the select all checkbox doesn't (directly) have anything to do with my ViewModel.
The code looks something like this:
<ListView>
<ListView.ItemTemplate>
<DataTemplate>
<CheckBox Content="Globale Eingabe"
Name="SelectSingle"
IsChecked="{Binding IsChecked}">
</CheckBox>
</DataTemplate>
<ListView.ItemTemplate>
</ListView>
<CheckBox Name="SelectAll" />
As you see the IsChecked Property of the SelectSingle is already bound to my ViewModel. So I reckon I need a trigger to manipulate the state of the checkbox.
Now I already tried sth like this:
<CheckBox Content="Globale Eingabe"
Name="SelectSingle"
IsChecked="{Binding IsChecked}">
<CheckBox.Triggers>
<Trigger SourceName="SelectAll" Property="IsChecked" Value="True">
<Setter TargetName="SelectSingle" Property="IsChecked" Value="True"/>
</Trigger>
</CheckBox.Triggers>
</CheckBox>
or sth like this:
<CheckBox Content="Globale Eingabe"
Name="SelectSingle"
IsChecked="{Binding IsChecked}">
<CheckBox.Triggers>
<DataTrigger Binding="{Binding ElementName=SelectAll, Path=IsChecked}"
Value="True">
<Setter TargetName="Check"
Property="IsChecked"
Value="True"/>
</DataTrigger>
</CheckBox.Triggers>
</CheckBox>
I also tried the same thing within a style, but to no avail. I always obtain an error, sth along the lines of "static member "IsCheckedProperty couldn't be found in type "ContentPresenter"".
Now that sounds as if the Target/SourceName binding wouldn't work, but why?
Is there something that I am missing?

I think that you should put the Check All logic in the ViewModel after all. In this Code Project article, WPF Guro Josh Smith solves similar problem (in his case it's TreeView and not ListView) in the ViewModel with the following title: "Putting the Smarts in a ViewModel".
I think it'd be easier to implement and debug this logic in the ViewModel, than to do some complicated MultiBinding that you wouldn't know where it'll bite you.
Last note - I'd always follow Josh's advice :-)

Torsten, I am sorry if I didn't understand what you've tried already, but you need to bind the IsChecked property of the CheckBoxes inside the ListView to the IsChecked property of the CheckBox outside it using:
IsChecked="{Binding Path=IsChecked, Mode=OneWay,ElementName=OutsideCheckBox}"

Related

Conditionally changing the Foreground of a WPF ComboBox item depending upon a value in the databound ItemsSource item

I have a WPF ComboBox bound to a Collection List<Users>. I have applied a DataTemplate to show the FirstName using a TextBlock and this works as expected:
<ComboBox Margin="5" ItemsSource="{Binding Path=TheUsers}" Name="cboUsers">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Margin="10" Text="{Binding Path=FirstName}">
</TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>`
I have an item in my User class called IsActive which is a Boolean value. If true then I want to set the Foreground of the TextBlock to Navy.
I have spent so much time on what should be so easy and looked all over the web but most articles talk about changing the overall colour or binding to another element in the xaml.
I tried implementing a DataTrigger and after an hour removed the code because it was not working. It would not recognise my field name. Does anyone have a very simple guide to how to do this or what would be the best approach?
As you apparently are not dealing with fields after all, this style should do what you want:
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsActive}" Value="True">
<Setter Property="Foreground" Value="Navy"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
It would not recognise my field name.
You cannot bind to fields, end of story.

Binding a Style DataTrigger to a custom ICommand's status property

I have a custom implementation of WPF's ICommand, that executes its bindings in a BackgroundWorker, so that the UI stays responsive.
I would like to display a custom effect while the bindings are being executed. For now, the effect is simplified to setting command source's IsEnabled property to False. Later, our designer will come up with some nice progress-style animation.
Here's an example of what I'm trying to do, that works (sort of):
<Button Width="80"
Command="{x:Static Member=local:AppCommands.Test}"
DataContext="{x:Static Member=local:AppCommands.Test}">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="IsEnabled" Value="True"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsExecuting, Mode=OneWay}" Value="True">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
As evident, my ICommand contains an IsExecuting property, which is set to True while the BackgroundWorker does its thing with the bindings, consequently disabling the button in the UI.
Unfortunately, having to explicitly set the button's DataContext to command instance prevents me from referring to the original DataContext in cases like this one:
<Button Width="80"
Command="{x:Static Member=local:AppCommands.ParamTest}"
CommandParameter="{Binding Path=SelectedItem}"
DataContext="{x:Static Member=local:AppCommands.ParamTest}">
Here, the CommandParameter should bind to the window's DataContext (which is set to an instance of my view-model), but instead it binds to the command which knows nothing about SelectedItem.
There are probably more ways to solve this, and I'm interested to hear all of them. I myself have been thinking along the lines of using an attached property to replace the direct binding to command's IsExecute and with it the need for setting the DataContext, but I'm not yet sure how to do that.
Any advice is most welcome. Thank you!
For now, I've come up with this simple solution:
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Command.IsExecuting, Mode=OneWay}" Value="True">
It does what I wanted so I'm happy. If anyone thinks there's a better way, I'm still interested, though.

Is it possible to highlight a ComboBoxItem, but not set it as the selected item?

I have a ComboBox that I am populating with a list of parts for a Return Authorization receiving app. In our RA system, a customer can specify a return for a Kit, but only actually return part of the kit. So because of this, my ComboBox shows a list of parts that belong to the kit, and asks the receiver to choose which part was actually received.
I have found the defaulting the selected item in my received part list to the part specified in the return makes to lazy receivers, and incorrect part information being received. So I have left the ComboxBox unselected.
What I would like to do is to highlight the specified part in the ComboBox, without actually selecting it. This way the actual part can be quickly found, while still requiring the user to actually choose it.
Although, this doesn't work, I think it will illustrate what I would LIKE to do:
<ComboBox Grid.Column="1" ItemsSource="{Binding Path=Part.MasterPart.FamilyParts}"
SelectedItem="{Binding Path=ReceivedPart, ValidatesOnDataErrors=True}" >
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Part.MaxId}"
Value="{Binding Path=Part.MaxId}">
<Setter Property="Background" Value="LightSalmon" />
</DataTrigger>
</Style.Triggers>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
You've got the right idea. The only thing I see wrong with your code is the DataTrigger attributes.
If Value was, well, just a value, it would work:
<DataTrigger Binding="{Binding Path=Part.MaxId}" Value="999" >
I would wrap this logic up into a new property on the viewmodel for simplicity:
<DataTrigger Binding="{Binding Path=Part.ShouldHighlight}" Value="true">
There are ways to highlight other than setting the background color, and I'd recommend you explore them because it can be confusing to users to have different background colors for different reasons (selection versus highlighting). For example, you could put a little star next to relevant items or make them bold.
That said, You can just do this to set the background color of the ComboBoxItem:
<ComboBox.ItemContainerStyle>
<Style TargetType="ComboBoxItem">
<Setter Property="Background" Value="{Binding Part.MaxId, Converter={StaticResource BackgroundConverter}}"/>
</Style>
</ComboBox.ItemContainerStyle>
Even better, use a view model and just bind directly to a BackgroundColor property:
<ComboBox.ItemContainerStyle>
<Style TargetType="ComboBoxItem">
<Setter Property="Background" Value="{Binding BackgroundColor}"/>
</Style>
</ComboBox.ItemContainerStyle>
Instead of adding a property to the view model, you could use a Style Selector (http://msdn.microsoft.com/en-us/library/system.windows.controls.styleselector.aspx) to determine which style to use for an item.
You're on the right track, but what I would do is put a bool read-only property in your Part class that told the combobox whether it should be highlighted in this instance. You could try something like this:
<ComboBox Grid.Column="1" ItemsSource="{Binding Path=Part.MasterPart.FamilyParts}"
SelectedItem="{Binding Path=ReceivedPart, ValidatesOnDataErrors=True}" >
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid>
<Border Background="LightSalmon" Visibility="{Binding Part.Highlighted, Converter={StaticResource BoolToVizConverter}}"/>
<TextBlock Text="{Binding Part.Name}"/>
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
This way, the background of the border wouldn't display at all if Highlighted were false.

How can I change styles of XAML file using Data Binding?

I'm binding a collection of objects to a listbox in WPF, for simplicity we'll say the object i'm binding has 3 propertys: Name, URL, IsBold. What I want to do, is have it displayed different if the IsBold is set to true, again as an example I want to set the TextBlock that Name appears in, to be bold. Is something like this even possible? Can I use a different style or something if one of my properties is a certain value? (can I do anything like an if/else in XAML)? I really have no idea where to start with this.
Say I have this in my DataTemplate
<TextBlock Style="{StaticResource notBold}" Text="{Binding Path=Name}"></TextBlock>
And if the IsBold is set to true for that particular Item I would like it to be (notice the style changes from 'notBold' to 'isBold')
<TextBlock Style="{StaticResource isBold}" Text="{Binding Path=Name}"></TextBlock>
Or something similar. I guess the more general question. Is it possible to change the apperance of something based on an item that's databound? And if it's not possible, how would something like this be done? Thru the code-behind somehow?
Thanks
What you'd normally do is write a DataTemplate for the objects in the list and then have a DataTrigger set the Fontweight of the TextBlock/TextBox based on the IsBold Property.
<DataTemplate DataType="DataItem">
<TextBlock x:Name="tb" Text="{Binding Name}"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsBold}" Value="true">
<Setter TargetName="tb" Property="FontWeight" Value="Bold" />
</DataTrigger>
<DataTrigger Binding="{Binding IsBold}" Value="false">
<Setter TargetName="tb" Property="FontWeight" Value="Normal" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
You'd then set a list of DataItems to the ItemsSource property of your ComboBox (either by Databinding or directly in the codebehind myComboBox.ItemsSource=myDataItems). The rest is done by WPF for you.

WPF Debugging datatriggers?

I am trying to do something very simple. I have a ToggleButton.IsChecked property bound to a bool. I want the background to toggle between red(false) and green(true). But for some reason it seems to be toggling between red and no background. I used a converter to check if I am getting proper notifications from the source and I am, so not sure why one trigger(false/red) works and the other(true/green) doesnt. Also would like to hear how people debug these kind of issues. Thanks!
Here is the code.
<DataTemplate x:Name"Flipper">
<StackPanel>
...
<ToggleButton IsChecked="{Binding Path=BoolValue,
Converter={StaticResource converter}}"
Name="onoff" >
</ToggleButton>
...
<StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding ElementName=onoff,Path=IsChecked}"
Value="True">
<Setter TargetName="onoff" Property="Background" Value="Green"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=onoff,Path=IsChecked}"
Value="False">
<Setter TargetName="onoff" Property="Background" Value="Red"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
Update: I changed the togglebutton to a checkbox and it works. No idea why...
Try using WPF Inspector:
https://wpfinspector.codeplex.com/
Once you attach to your running WPF application, highlight the element in question by holding down ctrl + clicking on it. Then, select the element in the visual tree (might be a parent) that contains the trigger. Click on the triggers tab and you can see the current evaluation (e.g. True == True). If the datatrigger condition is met, the little icon will be orange (lit).
It looks ok to me, can you try altering the converter to return "red" or "green" rather than True/False (and alter the trigger accordingly). I have seen some wierd behaviour with WPF triggers when using NULL or Booleans in that it "unsets" the property if it's the opposite of your trigger value, rather than using another trigger value.
As for debugging them.. I'd love to know if there's a better way than the hack and hope methods I generally use for XAML debugging :D

Resources