Multiselect WPF Listbox Make Multiple Selections With a Single Click - wpf

I have a databound multiselect listbox bound to a datatable. When I select a listboxitem I want some other listboxitems in the same listbox to be selected automatically. I want multiple items to be selected with a single click. How can i do that? I can't do it in SelectionChanged event because it leads to calling the same event again and breaks my logic altogether.
Please help. Any help will be highly appreciated.
UPDATE:
My listbox is already bound to a datatable which has a IsSelected column.I am using the value of this column in a style setter to make the listboxitem selected.Suppose i have 10 rows in the datatable.Now if the user selects the second listboxitem,i can get the isselected of the correspondong row in the database as 1.
But how can i get the other items to select at the same time? I think as Kent said,I rather use a property for binding. But how can i use a property to bind a listbox to a datatable?

Bind IsSelected to a property in your data class. When the property is changed, execute the logic to update the IsSelected property in other data objects:
<ListBox>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected" Value="{Binding IsSelected}"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Then in your data class you can have something like this:
public bool IsSelected
{
get { return _isSelected; }
set
{
if (_isSelected != value)
{
_isSelected = value;
OnPropertyChanged("IsSelected");
UpdateOtherItems();
}
}
}
Or you could have the data item raise an IsSelectedChanged event and have the owning class manage the interdependencies of the selection.

Would having a "SelectedItem" property with the logic in the setter for that property that would handle selecting your other 'like' items?
That's perhaps the way I would go, hard to say with out more details.

I am working on a similar thing.
I have single select combo-boxes that I load with the Selected Value property from the database, and now I am working on multi-select list boxes for-which I have a list of selections in the database I need to bind to the selected list for my list box.
I don't see a way to do it without a loop.
I see listbox read/write properties for getting or setting the Items, SelectedItem/Index/Value, or read only properties for Items or SelectedItems.

Maybe this is cheating, but, when you are adding the items in the SelectionChanged event have you tried setting IsEnabled false while you selected the multiple items and then setting it back to true afterwords, I think that is supposed to keep the controls events from firing?

I have created a MultiSelectCollectionView that you might find useful here:
http://grokys.blogspot.com/2010/07/mvvm-and-multiple-selection-part-iii.html

Related

Binding CommandParameter to code behind Property

I have a WPF View where I create controls dynamically depending on the object type in a List that the View is bound to in the ViewModel.
I have a Button on in the View that I have bound to a RelayCommand in the ViewModel but I also want to pass a CommandParameter to the Command.
The dynamically create controls are of types ListBox, ComboBox, TreeView, RadionButton and CheckBox. So when I press the Button I want to get all selected/checked items in the controls and pass this a List with the CommandParamter.
I have figured out how to search for all selected/checked items and get the object of type Code(class name) and put them in a List if I use the Click event on the Button. I want to use the RelayCommand instead of using Click Event.
I have managed to bind the CommandParameter to the a Property that calls GetAllSelectedCheckedCodes() but it is only bound when the View is created.
Is it possible to have a property in the code behind that calls the function GetAllSelectedCheckedCodes() that is bound first when the Button Command is triggered.
Or is it possible to have multiple controls add/remove items in a List in the ViewModel when they are selected/unselected or checked/unchecked?
Are you able to add a property to your class like IsSelected, or IsActive, and bind that to the the IsSelected or IsChecked property of the control? Then, when you want to act on the selected items, you could just grab all the items in the collection where IsActive == true.

How can the ViewModel request an update in the View in WPF/MVVM?

I have a dependency property on a control in my View that is bound to a field on my ViewModel. When the user clicks a menu item I want the control to update the value of that property so the ViewModel can save it in an XML file. What is the correct mechanism to have the ViewModel request that the View update that property?
Generally with MVVM controls update their bound properties (not fields) immediately as they are edited. The ViewModel is the "state", the View is just one way of seeing that state.
Your control should update the ViewModel whenever it is edited. Your ViewModel can then save it to XML when the menu command is invoked.
I had the problem that the viewmodel was not updated when clicking on a menuitem right after writing in a TextBox.
With the parameter UpdateSourceTrigger=PropertyChanged, it worked for TextBoxes:
<TextBox Grid.Column="5" Grid.Row="7" Text="{Binding SelectedPerson.Room, UpdateSourceTrigger=PropertyChanged}"></TextBox>
But unfortunately not for DatePickers...
The strange thing is that when clicking on a button instead of the menuitem, the DatePicker is updating the viewmodel.
As I don't have more time to look for a bugfix right now, I'll just change my menuitems into buttons.
Edit: the Problem is not the menuitem but the menu itself. When I move the menuitems out of the menu, it works.
Your object must implement INotifyPropertyChanged interface and your properties should look like this
private string _property;
public string Property
{
get { return _property; }
set
{
if(_property == value) return;
_property = value;
RaisePropertyChanged("Property");
}
}
so every change made to the property will be cascaded to view through the binding mechanism.
The menu item command property will be bound to a command declared in the view model and it will trigger a method on view model and set the property value. The change will be cascaded to view:
menuItem.Click -> menuItem.Command.Execute -> viewModel.method -> change the view model property -> raise property changed event -> view property changed through binding

WPF TreeView ItemsSource not keeping values

I am using a wpf treeview and binding the ItemsSource to an IEnumerable of my ViewModel that has an IsChecked Property. I am binding a checkbox to this value with a Mode of TwoWay. I can see when I step through the program that it is setting this value properly on my ViewModel when I check the checkbox.
I then have a Menu Item that "Runs Checked". In this method I have a foreach loop that runs through the ItemsSource as IEnumerable of ViewModel looking for IsChecked = true to queue up the checked items to be run by a separate program. As such:
foreach (AccountViewModel account in tvClientList.ItemsSource as IEnumerable<AccountViewModel>)
{
if (account.IsChecked)
{
context.Queues.InsertOnSubmit(new Queue {Id = account.Id});
}
}
However, account.IsChecked is always false. Why is this?
i would check the following.
does the setter of AccountViewModel.Ischecked is called when clicking the treeview checkbox. if no - then thats the problem if yes you should look at your collection bindings.
debug your foreach and check wether the treeviewitemssource is the collection you expect.
maybe you can post your bindings, if that all no help.
ps: dont access your View controls directly if you use viewmodels/mvvm.
Just for anyone else encountering this issue. ItemsSource returns a new set of data, Items, however contains the current set of data.

WPF: Detect when selected item changes

I have a control that is data-bound to a ListBox. All of the bound properties are being updated correctly. However, the control needs to know when the selected item changes so that it can do some other cleanup. Is there an event that covers this?
You can also bind to the SelectedItem property, say with ICollectionView.CurrentItem, and set the IsSynchronizedWithCurrentItem property to True.
There is SelectionChanged event in ListBox.

Problem with ItemTemplate TextBlock

i am trying to make an item template where some of the field in my stack panel can be empty. When it's empty, I would like to set the visiblility to collapsed. I tried putting triggers but it doesn't seem to work and I am not very familiar with this part of WPF
Also, I would like to change the color of the background of this item when a specific value in my binding is true. Is it the same thing?
Thanks.
Using a ViewModel is one approach to solving this kind of problem.
The if your data was stored in an Item class you would make an ItemViewModel to wrap the Item for display in your items control. The ViewModel class would implement INotifyProperty changed in order to update the display and the setters would raise the PropertyChanged event passing the appropriate property name. You can also raise property changed events for as many interrelated changed fields as necessary.
Suppose you wanted Item.Description to display in a collapsed field when Description is empty. Your ViewModel properties could look like this
public string Description
{
get { return mItem.Description; }
set { mItem.Description = value; Notify("Description"); Notify("DescriptionVisibility"); }
}
public Visibility DescriptionVisibility
{
get { return string.IsNullOrEmpty(mItem.Description) ? Visibility.Visible : Visibility.Collapsed; }
}
In the XAML bind the text property to Description and the Visibility property to DescriptionVisibility.
If you want to hide an item if it's content is null, you have to redefine the ControlTemplate of its ListBoxItem (or ListViewItem or something else depending on which item container you're using) and use triggers that target the DataContext, like:
<DataTrigger Binding="{Binding}" Value="{x:Null}">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
However, I'd suggest that you use the Filter delegate on your CollectionView to exclude your empty items from your view directly, to avoid collapsing unused items.
For example to exclude null objects, in your code behind, use:
CollectionViewSource.GetDefaultView(yourCollection).Filter = o => o != null;

Resources