How to bind a ListBox itself - c#

I know how set bindings for i.e. the ItemSource or the SelectedItem of a ListBox. My Problem now is, that I have no clue how to bind the ListBox itself to a ListBox variable in my ViewModel to perform actions like ListBox.ClearSelected().

Instead of trying to clear listbox itself, try to set Selected item to NULL
Passing UI Elements to view model is only going to create many many many more issues.
<ListBox SelectedItem="{Binding Path=SelectedItemProp}"/>
VM
SelectedItemProp = null;

Related

Binding ObservableCollection to selected items of a ListBox

After hours and hours of googling, I still can't find a simple solution for binding an ObservableCollection to the selected items of a ListBox in a TwoWay Mode...
What I have is really simple : a ListBox with SelectionMode="Multiple", and an ObservableCollection<Contact> named SelectedContacts. I want this two to be bound. Of course my ListBox has ItemsSource="{Binding Contacts}" which is another ObservableCollection of Contact.
Now I really can't use a IsSelected bool on my Contact items, I just can't.
Thank you !
There is no simple solution. You can't bind SelectedItems.
The best solution is to select your Contact items into a view model object with an IsSelected property, bind to that, and then run a query against the primary OC when you need to get the selected items collection.
Since you said you can't/won't do that, the next best solution would likely be to handle SelectionChanged in your code-behind and manually update the VM collection from there.
Since SelectedItems is not a DependencyProperty you are not allowed to use Bindings
But there is a solution, take a look at this post:
http://blogs.microsoft.co.il/miziel/2014/05/02/wpf-binding-listbox-selecteditems-attached-property-vs-style/
Another option is to not keep track of the selected items in your ViewModel. Instead, pass them as a CommandParameter from the UI when you are trying to do some action.
Example:
<ListBox x:Name="MyListBox"
ItemsSource="{Binding SomeCollection}" />
<Button Command="{Binding SomeCommand}"
CommandParameters="{Binding SelectedItems, ElementName=MyListBox}" />

Two-way binding combobox to enum

I have a View that is linked to my ViewModel using a DataTemplate, like this
<DataTemplate DataType="{x:Type ViewModels:ViewModel}">
<Views:View />
</DataTemplate>
The ViewModel holds a property ProcessOption that is of type MyEnum?, where MyEnum is a custom enumeration that has let's say 3 values: Single, Multiple and All. I am trying to bind a combobox to this property, so the approach I am following is:
ViewModel has a property of List<string> that is
public List<string> Options
{
get
{
return Enum.GetNames(typeof(MyEnum)).ToList();
}
}
to which I bind the ItemsSource property of the Combobox. Then, in addition to the ProcessOption property, the ViewModel also has an OptionName property (of string), which is intended to hold the selected option's name. The ViewModel implements INotifyPropertyChanged and both properties raise the PropertyChanged event in their setters. The binding I am using then is:
<ComboBox ItemsSource="{Binding Options}"
SelectedItem="{Binding OptionName}"
SelectedValue="{Binding ProcessOption}"/>
This works fine up to this point. Initially the combobox is empty and both properties are null, and when the user selects an option this is propagated to the ViewModel as it should.
The problem appears when I load the data from a Database, and I want to load the controls with initial values. In this case, in the ViewModel's constructor I have this:
this.ProcessOption = objectFromDB.ProcessOption // this is the value restored from DB, let's say it is MyEnum.Multiple
this.OptionName = Options.First(x => x.Equals(Enum.GetName(typeof(MyEnum), objectFromDB.ProcessOption)));
The problem is, although the above sets the two properties to their correct values, they are later set to null from the Combobox binding, so the initial values are not kept. I have also tried to do something like if (value == null) { return; } in the properties' setters, in which case they have the correct values after the View loads, however the Combobox still does not display the correct option, it is empty.
I should also note that I've also tried setting IsSynchronisedWithCurrentItem and it doesn't make any difference, apart from the fact that the first element is displayed instead of the combobox being empty.
Can anyone help with this binding? Any help will be very much appreciated, this is driving me crazy!
<ComboBox ItemsSource="{Binding Options}"
SelectedItem="{Binding OptionName}"
SelectedValue="{Binding ProcessOption}"/>
Your binding doesn't look like it should work at all -- you don't have TwoWay binding set up, and I think SelectedItem and SelectedValue is an either/or proposition.
I suggest that you get rid of OptionName and just bind SelectedItem to ProcessOption (TwoWay) with an IValueConverter that will convert to/from string.

Changing Data Context for Data Template clears Combo Box selection

I have a TreeView that permits the user to select different items. The display for each item is determined using Data Templates with the DataType set to the appropriate ViewModel type. The DataContext is automatically set based on the selected item in the tree view to the appropriate ViewModel.
Here's the problem:
One of the DataTemplates has a ComboBox bound to an ObservableCollection to get the list of items and a property to get/set the SelectedValue in the ViewModel.
When I select one item of this type, and then select another item of the same type, the ComboBox displays blank instead of the correct selected item. It appears that the Combo Box is setting the SelectedValue property to NULL immediately after the transition to the new item, and then never updating.
<ComboBox Margin="1,0"
ItemsSource="{Binding ItemsToSelect}"
SelectedValue="{Binding SelectedValue}"
SelectedValuePath="ValuePath" DisplayMemberPath="DisplayPath"
IsEnabled="{Binding CanSelectItem}">
</ComboBox>
The really strange part is if I select an item of a different type between selecting items of the same type, it always displays correctly.
I've tried ignoring the NULL value in the SelectedValue setter, and that didn't work regardless of whether I also raised the PropertyChanged event or not.
private MyObject selectedValue;
public MyObject SelectedValue
{
get
{
return selectedValue;
}
set
{
if (value != null)
{
this.selectedValue = value;
}
this.OnPropertyChanged("SelectedValue");
}
}
Looking at the similar questions while writing this lead me to an interesting attribute that I hadn't found yet - IsSynchronizedWithCurrentItem from this question. At first, I thought this solved the problem, but alas it just changes the behavior somewhat.
With this attribute set to True, the combo doesn't entirely clear its selection, but instead just marks the first item as selected. So, instead of being set to NULL, now the SelectedValue property is being set to the first item in the list.
Anyone have any ideas for a solution?
If I understand your problem correctly, a couple of things are going on here.
First you do not have Mode=TwoWay, UpdateSourceTrigger=PropertyChanged} set in your bindings.
Second, the property binding will only update if there is a change in the value itself.
Check this out Data Binding
I figured out a work around, but it isn't quite what I wanted.
I changed the binding to use SelectedItem instead of SelectedValue, and the issue doesn't occur.
I got the idea from this question.
So I changed
SelectedValue="{Binding SelectedValue}"
To (and renamed my ViewModel Property):
SelectedItem="{Binding SelectedItem}"
After updating the uses of this property in the ViewModel, everything worked.

Combobox triggers

I have dialog which contains a combobox
<ComboBox Margin="0,1,34,36" Grid.Row="1" Grid.Column="1" ItemsSource ="{Binding Path=CompanyView}" DisplayMemberPath="CompanyName" IsSynchronizedWithCurrentItem="True"
SelectedItem="{Binding Path=SelectedCompany}"
The itemsource is bound to a collectionviewsource and the selected item is bound to a property in my viewmodel which is non shared
private Company selectedCompany;
public Company SelectedCompany
{
get{ return this.selectedCompany;}
set
{
this.selectedCompany = value;
FilterString = this.selectedCompany.Id;
}
}
I can open and close the dialog as many times as i want without any problem . My problem is that
if i select a item in the company combo and then closes the dialog, when i open the dialog again the form tries to set the SelectedCompany which in this case i null. I could check for null but i would rather understand why this is happening.
The most likely cause is that CollectionViewSource tracks its own SelectedItem, and this item is probably null. So when it binds ItemsSource it is also trying to bind SelectedItem to the CollectionViewSource.SelectedItem at the same time. After that binding completes, the regular SelectedItem binding runs, however by this point SelectedCompany has been set null.
If this is the case, I would suggest staying away from CollectionViewSource and binding to a straight collection instead.
Seems to me that the problem might be that you have different instances of window/viewmodel and opening a new dialog might create a new instance of the VM which has the selectedCompany default to null. Is this your case?

Is it possible to add a default ComboBox entry with command binding in XAML?

I'm working on my first true WPF MVVM pattern application.
Currently I have a number of ComboBoxes on various screens that are bound to Collection classes and properties of the relevant ViewModel class.
They always have an entry with the text <Add>, which is really an empty object class and I currently use it to trigger an AddNewObject event if the Property bound to the SelectedItem has <Add> in its ToString() output. This strikes me as cumbersome and it ties the View too closely to the View model for my liking.
e.g.
<ComboBox ItemsSource="{Binding AllObjects}" SelectedItem="{Binding SelectedObject}" />
then in ViewModel code:
public SomeObjectType SelectedObject
{
get{return this.fieldSomeObjectType;}
set
{
if(null==value)
return;
if(value.ToString().Contains(#"<Add>"))
{
if(null!=this.AddNewObject)
{
this.AddNewObject;
}
}
}
}
Is there a way in XAML of adding this extra line into the ComboBox drop down list and binding it to an AddNewObject Command?
The code you've written in your view has nothing to do with your business logic. Its fine.
MVVM doesn't say that you shouldn't have anything in the codebehind of the view. Showing 'Add' is a requirement on the view and can be handled by the code behind of view.
In ASP.NET I've been doing this that I databinded the list control to some data but also specified some items in the html and it would merge them. Have you tried that?
use CompositeCollection for merging a default item with a itemsource. http://msdn.microsoft.com/en-us/library/ms742405.aspx

Categories

Resources