I'm trying to get my ListCollectionView to bind to a combo box. However, it seems to only work when I bind to my ObservableCollection.
Properties:
private ListCollectionView sitesView;
public ListCollectionView SitesView
{
get { return sitesView; }
set
{
sitesView = value;
RaisePropertyChanged(() => SitesView);
}
}
public ObservableCollection<ISite> SitesCollection { get; set; }
Constructor:
SitesCollection = new ObservableCollection<ISite>();
SitesView = (ListCollectionView)CollectionViewSource.GetDefaultView(SitesCollection);
When binding like so:
<ComboBox Grid.Row="2" ItemsSource="{Binding SitesView, Mode=TwoWay}"/>
any item I add to SitesCollection does not get shown when I click the drop down in my combo box. But if I do the binding like so:
<ComboBox Grid.Row="2" ItemsSource="{Binding SitesCollection, Mode=TwoWay}"/>
it works fine and I see the items when I click the drop down.
Attempts at fixing: After I add the an item to the SitesCollection, I tried to raise property change notifications on both the ListCollectionView and the ObservableCollection and it didn't make a difference. Any ideas?
I didn't have time to test my answer; I apologize and will follow up.
I think your issue is because CollectionViewSource.GetDefaultView(...)
returns an ICollectionView, which I believe is essentially just a wrapper that enables the underlying data to be sorted.
Try setting SitesView to the SourceCollection of the DefaultView.
SitesView = (ListCollectionView)CollectionViewSource.GetDefaultView(SitesCollection).SourceCollection
Related
I'm trying to set a default value into a combo box when the application is first loading using the MVVM pattern and it looks like this is all the time unset, combo box being all the time empty when the page loads.
This is my xaml:
<ComboBox Grid.Row="0" Margin="10,0,0,0" Grid.Column="1"
SelectedItem="{Binding Path=JuiceOperations.SelectedItemOption, Mode=TwoWay}"
SelectedIndex="{Binding Path=JuiceOperations.SelectedComboBoxOptionIndex, Mode=TwoWay}"
SelectedValue="{Binding Path=JuiceOperations.SelectedComboBoxOptionIndex, Mode=TwoWay}"
ItemsSource="{Binding Path=JuiceOperations.JuiceOptions}" />
This is the view model code, with its default constructor:
public JuiceViewModel()
{
juiceOperations.SelectedComboBoxOptionIndex = 0;
juiceOperations.SelectedItemOption = "Cola";
}
where I am trying to set the default value of the combo box.
And this is how the properties looks like:
private List<string> juiceOptions = new List<string> { "Cola", "Sprite", "Fanta", "Pepsi" };
private string selectedItemOption = string.Empty;
private int selectedComboBoxOptionIndex = 0;
public int SelectedComboBoxOptionIndex
{
get
{
return this.selectedComboBoxOptionIndex;
}
set
{
this.selectedComboBoxOptionIndex = value;
this.OnPropertyChanged("SelectedComboBoxOptionIndex");
}
}
public List<string> JuiceOptions
{
get
{
return this.juiceOptions;
}
set
{
this.juiceOptions = value;
}
}
public string SelectedItemOption
{
get
{
return this.selectedItemOption;
}
set
{
this.selectedItemOption = value;
this.OnPropertyChanged("SelectedItemOption");
}
}
When selecting an item from combo box the selection is updated into the model and also into the view, so it is working as expected but when the page is first loaded even if the "SelectedComboBoxOptionIndex" and "SelectedItemOption" are being called and their value updated the view of the page is not updated and the empty string is being shown into the combo box where I was expected to see the "Cola" value, instead of the empty string.
Can someone explain me what I am doing wrong and how should I set the default "Cola" value into the combo box ?
Only bind the SelectedItem property of the ComboBox to the SelectedItemOption source property and set the latter to the string "Cola" in the view model. This should work:
<ComboBox Grid.Row="0" Margin="10,0,0,0" Grid.Column="1"
SelectedItem="{Binding Path=JuiceOperations.SelectedItemOption}"
ItemsSource="{Binding Path=JuiceOperations.JuiceOptions}" />
public JuiceViewModel()
{
juiceOperations.SelectedItemOption = "Cola";
}
Don't mix SelectedItem, SelectedIndex and SelectedValue. You only need one.
mm8 above absolutely right, that should fix your issue.
On a side note, what you have there will work for a static selection list, but consider using an ObservableCollection<string> instead of a List<string>. The former implements INotifyCollectionChanged, which allows the view to be notified if there has been a change in the collection. When you bind an Observable Collection to the view, the view automatically subscribes to the CollectionChanged event. You will need this if you ever need to add or remove options at run time. Side note, OnCollectionChanged will not fire if you simply modify an item, for that you would still need to callOnPropertyChanged("JuiceOptions") in the setter.
something like this (with the appropriate private backing field):
public ObservableCollection<string> JuiceOptions
{
get
{
return this.juiceOptions;
}
set
{
this.juiceOptions = value;
this.OnPropertyChanged("JuiceOptions");
}
}
The value of juiceOperations.SelectedItemOption, that is, "Cola", is not the same "Cola" stored in the ItemsSource. You would need to do something like juiceOperations.SelectedItemOption = juiceOperations.JuiceOptions.First().
I've a list box but if I click on an item, I must see the details of that item. I've made this code where I try to bind the SelectionChanged event to a property whit type RelayCommand and mode is two way.
<ListBox Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3"
SelectedItem="{Binding SelectedVillage, Mode=TwoWay}"
ItemContainerStyle="{StaticResource lstidflt}"
SelectionChanged="{Binding SelectedVillageChanged, Mode=TwoWay}"
ItemTemplate="{StaticResource weatheritemdt}"
ItemsSource="{Binding VillageList}" />
This doesn't work of course because you can't bind an event to a property or a property to a method and vice versa. You can only bind a property to a property. So the question is now are there alternatives to bind a SelectionChanged event to a property?
I use C# in a Windows universal 10 application with the MVVM light architecture.
You could just let the binding of the SelectedItem property
<ListBox ItemsSource="{Binding VillageList}" SelectedItem="{Binding SelectedVillage, Mode=TwoWay}" />
And do the job in the setter
public class VillageViewModel
{
public ObservableCollection<Village> VillageList { get; set; }
private Village selectedItem;
public Village SelectedItem
{
get { return selectedItem; }
set
{
if (selectedItem == value)
return;
selectedItem = value;
// Do logic on selection change.
}
}
}
What I do (in WPF) is bind the selected item to a full property then raise the event in the set part. It will look something like this;
private Village _SelectedVillage;
public Village SelectedVillage{
get {return _SelectedVillage;}
set {
_SelectedVillage = value;
RaiseEvent myEvent();
}
}
You can also raise the relaycommand or check for a trigger in xaml. If you go with the property, look at dependency property if it's available in win 10 universal.
i have a ObservableCollection with some data. They are displayed as Master (ListBox) and Detail (some Labels). I use binding and IsSynchronizedWithCurrentItem to show the correct details to the selected master item. This works all fine. Now i want to edit some details (load different image). I implemeted this a a Button Command in the ViewModel.
But how do i know which item is selected (UI) in the ViewModel-layer ?
Thanks for help
I don't really find the IsSynchronizedWithCurrentItem property that useful in MVVM scenarios.
Just expose another SelectedItem property in the ViewModel.
public ItemType SelectedItem
{
get { return _selectedItem; }
set
{
_selectedItem = value;
// your logic here
}
}
You need to bind a value or Enumerable of values of your ViewModel to the ListBox's SelectedItems property.
SelectedItems="{Binding VMProperty}"
http://msdn.microsoft.com/en-us/library/system.windows.controls.listbox.selecteditems(v=vs.110).aspx
If you only want one item selected you need to set:
SelectionMode="Single"
SelectedItem="{Binding VMProperty}"
If I understood you right, what you are looking for is the following
<ListBox SelectedItem="{Binding ObjectName, UpdateSourceTrigger=PropertyChanged}"/>
Plus under your ViewModel you have to declare the following
public YourObject ObjectName { get; set; }
Simple as that!
The normal way to detect which item in the collection is currently selected in the UI is to data bind a property of the same type as the items in the collection to the ListBox.SelectedItem property:
<ListBox ItemsSource="{Binding SomeCollection}"
SelectedItem="{Binding SomeProperty}" />
Now, whenever the user selects a new item, the SomeProperty setter will be called:
public YourDataType SomeProperty
{
get { return someProperty; }
set
{
someProperty = value;
// The value has just changed
}
}
I have a ListBox simplified to the following XAML
<ListBox ItemsSource="{Binding Properties}"
DisplayMemberPath="Name"
SelectedItem="SelectedProperty" />
and in my ViewModel:
private List<Property> propertyList;
private Property selectedProperty;
public List<Property> Properties
{
get
{
return propertyList;
}
set
{
propertyList = value;
NotifyPropertyChanged("Properties");
}
}
public Property SelectedProperty
{
get
{
return selectedProperty;
}
set
{
NotifyPropertyChanged("SelectedProperty");
selectedProperty= value;
}
}
My List box populates fine, but no matter what I try I cannot seem to get the SelectedProperty to update when I select an item in my list box. I have tried switching it all around to use ObservableCollection rather than List and adding an Event handler for CollectionChanged, but this has not worked.
I am sure I am missing something stupid, and cannot see the wood for the trees. I am reaching the end of my tether and need someone to step in and help.
You need to bind to the SelectedProperty:
<ListBox ItemsSource="{Binding Properties}"
DisplayMemberPath="Name"
SelectedItem="{Binding SelectedProperty}" />
I need to create an Auto search control which will show the results as rows as this one http://www.devexpress.com/Products/NET/Controls/WPF/Editors/lookup-editor.xml. However, I dont need the graphics and checkboxes here. A simple listview like appearance will work.
Please suggest how to create the user control using WPF.
Here has a nice article on Sorting, Filtering and Grouping ListView.
Basically you set CollectionViewSource to ListCollectionView. You can then use the Filter Property to filter the ListView.
If you're using an MVVM approach you could do the following:
Bind your search Textbox Text member, ListView's ItemsSource and SelectedItem to the ViewModel
Set 'UpdateSourceTrigger=PropertyChanged' on the TextBox's binding
In the setter of the property that the TextBox is bound to add logic that searches the ItemsSource collection and sets the SelectedItem bound property.
Something like this:
XAML:
<TextBox Text="{Binding Path=SearchTerm, UpdateSourceTrigger=PropertyChanged}"/>
<ListView ItemsSource="{Binding Path=SourceCollection}" SelectedItem="{Binding Path=SelectedSearchItem, Mode=TwoWay}" />
Code:
public class ViewModel : INotifyPropertyChanged
{
public string SearchTerm
{
get { return searchTerm; }
set {
searchTerm = value;
SelectedSearchItem = SourceCollection.FirstOrDefault(foo => foo.Name.Contains(searchTerm));
}
}
public Foo SelectedSearchItem
{
get { return selecedSearchItem; }
set {
selectedSearchItem = value;
// Raise PropertyChanged
}
}
public ObservableCollection<Foo> SourceCollection { get; set;}
}