Changing complete lists of content in Combo Boxes - c#

In my program I have a comboBox and a listBox. The listBox is full of different commands. The selectedItem and contents of the comboBox depend on which command is selected. The selectedItem in the comboBox stays selected for that command. For example, when the user has content selected in the comboBox and they switch to a different command, and then switch back, the same item will still be selected in the comboBox.
Because the comboBox gets populated with different items depending on which command is selected should I make an ObservableCollection for each set of items? I'm only allowed to bind the ItemsSource to one thing, so how would that work?
If that's not the right approach please advise. If this isn't clear enough, please let me know.
Thanks!
Here's a sample of what my program will look like:
Then, if command 2 is selected, the list in the combo box might be a, b, c, d, e, for example.

You can have a separate ObservableCollection for each listbox command.
When the user selects a new listbox command, set the comboBox.ItemsSource to the appropriate ObservableCollection. That should solve your problem.

Based on your description, the contents of the combobox are tied to the selected item in the listbox. Without knowing any more of the details, seems like your business object would be a “Command” object that contains an ObservableCollection of “SubCommand”? objects. Your application would then contain an Observablecollection of “Command” objects. The listbox would be data bound to the "Command" objects list, and the combobox would be bound to the selected items "SubCommand" collection.

Seems to me you're looking for a Master / Detail structure here:
Data Items:
public class MyCommandDefinition
{
public string DisplayName {get;set;}
public List<MyParameter> Parameters {get;set;}
public Parameter SelectedParameter {get;set;}
}
public class MyParameter
{
public string DisplayName {get;set;}
//Additional properties depending on your needs.
}
ViewModel:
public class MyViewModel
{
public List<MyCommandDefinition> Commands {get;set;}
public MyCommandDefinition SelectedCommand {get;set;}
}
XAML:
<ListBox ItemsSource="{Binding Commands"}"
SelectedItem="{Binding SelectedCommand}"
DisplayMemberPath="DisplayName"/>
<ComboBox ItemsSource="{Binding SelectedCommand.Parameters}"
SelectedItem="{Binding SelectedCommand.SelectedParameter}"
DisplayMemberPath="DisplayName"/>
Don't forget NotifyPropertyChanged() in all these properties if you're going to change them programatically and expect that to be reflected in the UI.

Related

WPF ComboBox doesn't display default value with SelectedIndex [duplicate]

What is the difference betweeen the following:
SelectedItem
SelectedValue
SelectedValuePath
All these dependency properties are defined in Selector class. I often confuse SelectedItem with SelectedValue , and SelectedValue with SelectedValuePath.
I would like to know the difference between them, and also when do we use them, especially SelectedValue and SelectedValuePath. Please explain their use with some simple examples.
Their names can be a bit confusing :). Here's a summary:
The SelectedItem property returns the entire object that your list is bound to. So say you've bound a list to a collection of Category objects (with each Category object having Name and ID properties). eg. ObservableCollection<Category>. The SelectedItem property will return you the currently selected Category object. For binding purposes however, this is not always what you want, as this only enables you to bind an entire Category object to the property that the list is bound to, not the value of a single property on that Category object (such as its ID property).
Therefore we have the SelectedValuePath property and the SelectedValue property as an alternative means of binding (you use them in conjunction with one another). Let's say you have a Product object, that your view is bound to (with properties for things like ProductName, Weight, etc). Let's also say you have a CategoryID property on that Product object, and you want the user to be able to select a category for the product from a list of categories. You need the ID property of the Category object to be assigned to the CategoryID property on the Product object. This is where the SelectedValuePath and the SelectedValue properties come in. You specify that the ID property on the Category object should be assigned to the property on the Product object that the list is bound to using SelectedValuePath='ID', and then bind the SelectedValue property to the property on the DataContext (ie. the Product).
The example below demonstrates this. We have a ComboBox bound to a list of Categories (via ItemsSource). We're binding the CategoryID property on the Product as the selected value (using the SelectedValue property). We're relating this to the Category's ID property via the SelectedValuePath property. And we're saying only display the Name property in the ComboBox, with the DisplayMemberPath property).
<ComboBox ItemsSource="{Binding Categories}"
SelectedValue="{Binding CategoryID, Mode=TwoWay}"
SelectedValuePath="ID"
DisplayMemberPath="Name" />
public class Category
{
public int ID { get; set; }
public string Name { get; set; }
}
public class Product
{
public int CategoryID { get; set; }
}
It's a little confusing initially, but hopefully this makes it a bit clearer... :)
Chris
To answer a little more conceptually:
SelectedValuePath defines which property (by its name) of the objects bound to the ListBox's ItemsSource will be used as the item's SelectedValue.
For example, if your ListBox is bound to a collection of Person objects, each of which has Name, Age, and Gender properties, SelectedValuePath=Name will cause the value of the selected Person's Name property to be returned in SelectedValue.
Note that if you override the ListBox's ControlTemplate (or apply a Style) that specifies what property should display, SelectedValuePath cannot be used.
SelectedItem, meanwhile, returns the entire Person object currently selected.
(Here's a further example from MSDN, using TreeView)
Update: As #Joe pointed out, the DisplayMemberPath property is unrelated to the Selected* properties. Its proper description follows:
Note that these values are distinct from DisplayMemberPath (which is defined on ItemsControl, not Selector), but that property has similar behavior to SelectedValuePath: in the absence of a style/template, it identifies which property of the object bound to item should be used as its string representation.
SelectedItem and SelectedValue are an object.
and SelectedValuePath is a string.
for example using the ListBox:
Below listbox1.SelectedValue becomes a string value.
string value = listbox1.SelectedValue;
if you say give me listbox1.SelectedItem it will give you the entire object.
ListItem item = listbox1.SelectedItem;
string value = item.value;
inspired by this question I have written a blog along with the code snippet here. Below are some of the excerpts from the blog
SelectedItem – Selected Item helps to bind the actual value from the DataSource which will be displayed. This is of type object and we can bind any type derived from object type with this property. Since we will be using the MVVM binding for our combo boxes in that case this is the property which we can use to notify VM that item has been selected.
SelectedValue and SelectedValuePath – These are the two most confusing and misinterpreted properties for combobox. But these properties come to rescue when we want to bind our combobox with the value from already created object. Please check my last scenario in the following list to get a brief idea about the properties.
Every control that uses Collections to store data have SelectedValue, SelectedItem property. Examples of these controls are ListBox, Dropdown, RadioButtonList, CheckBoxList.
To be more specific if you literally want to retrieve Text of Selected Item then you can write:
ListBox1.SelectedItem.Text;
Your ListBox1 can also return Text using SelectedValue property if value has set to that before. But above is more effective way to get text.
Now, the value is something that is not visible to user but it is used mostly to store in database. We don't insert Text of ListBox1, however we can insert it also, but we used to insert value of selected item. To get value we can use
ListBox1.SelectedValue
Source

How can I set the collection object in database table using SQlite?

I am developing a WPF application in which I have a class 'Movie' which contain some properties and another class MovieCollection(which is the collection of movie). Right now I have bind this collection with my DataGrid in xaml to show Movie properties. I am taking user input by opening new window at run time and populate the observable collection with that to show it in my DataGrid, but now I want to store data in database first and fetch that data from database to show it in DataGrid. MovieCollection class is something like this
ObservableCollection<Movie> _movieObservableCollection=new ObservableCollection<Movie> ();
public ObservableCollection<Movie> MovieObservableCollection
{
get { return _movieObservableCollection; }
set
{
_movieObservableCollection = value;
this.NotifyPropertyChanged("MovieObservableCollection");
}
}
Here I want to set this collection such that the properties of model class shown as the columns attributes of the table.
How can I do this?
How can I proceed with this?
Any link?
If you bind this collection to your DataGrid, you can make use of the AutoGenerateColumns property.
<DataGrid ItemsSource="{Binding MovieObservableCollection}"
AutoGenerateColumns="True"
...
For more information, see the documentation.

How to databind WPF controls to an ObservableCollection to store filled in values?

I've got a Windows 8 Store form with multiple controls, a.o. lots of comboboxes, 2 I show below. I can populate them using databinding to a number of ObservableCollections (most used in multiple comboboxes, like prMachType). This works to databind the content to display.
<ComboBox x:Name="machinetype" ItemsSource="{Binding prMachtype}" SelectedItem="{Binding SelectedClass, Mode=TwoWay}" />
However I am not sure how to get the results of the controls the user enters into another ObservableCollection. The 'set' below is called (only when I add Mode=TwoWay in the XAML) when I change a value in the combobox machinetype:
public SchwDescr SelectedClass
{
get
{
return _SelectedClass;
}
set
{
if (_SelectedClass != value)
{
_SelectedClass = value;
RaisePropertyChanged("SelectedClass");
}
}
}
_SelectedClass contains the properties of the assigned ObservableCollection (like Description and Key) but now I would need to have this key (e.g. "00005") and field used (machinetype, as in the name of the combobox) together to store in another ObservableCollection (containing Field + Key, so machinetype and "00005" when this combobox is selected. I do not see which control (here combobox machinetype) the user is changing here so I can't store the field+selection 'manually' and I also don't see how I can databind directly to such an ObservableCollection so key+field are update directly and also show the (stored) selection when I load the data again (the preferred way of course).
Can someone lead me to the right direction (like a full sample)?

How can I programatically select a listview item from within the viewmodel?

I have a MVVM application with a MainWindowViewModel connected to a MainWindowview.
On the MainWindow view I have a ComboBox containing stock ticker symbols.
I have another viewmodel and view called AllStockQuoteViewModel connected to AllStockQuoteView which contains a list of stocks and their prices.
I want to be able to select an item from the ComboBox and have the item in the AllStockQuoteView selected and highlighted. On my MainWindowViewModel I have saved the reference to the AllStockQuoteViewModel and use it to call a method to find the stock ticker symbol in the ObservableCollection bound to the AllStockQuoteView, but haven't found a way to programmatically select the item on the AllStockQuoteView.
I have a SelectedQuote property on the AllStockQuoteViewModel bound to the listview on the AllStockQuoteView and I can select one of the items and my SelectedQuote property is set fine. If I set this programmatically in my SelectQuote method, it doesn't appear as if the item is selected in the view, although the item is passed back to the MainWindowViewModel and I can use it to populate the textblocks on MainWindow view.
I'd like to be able to show the item on the AllStockQuoteView as being selected via highlighting as if the user selected it.
How can this be done?
Its very easy to implement
You need two things in your view model
A List of your objects and a selected item property
private CustomObject _selectedCustomObject;
public ObservableCollection<CustomObject> CustomObjects
{
get
{
return new ObservableCollection<CustomObject>();
}
}
public CustomObject SelectedCustomObject
{
get { return _selectedCustomObject; }
set
{
if (_selectedCustomObject== value)
{
return;
}
_selectedCustomObject= value;
PropertyChanged.Raise(this, x => x.SelectedCustomObject);
}
}
Then in your view you add your List/Combo control and bind to both properties.
<ListView ItemsSource="{Binding CustomObjects}"
SelectedItem="{Binding SelectedCustomObject}">
Then all you need to do is set the viewmodel properties and the view will update.
First you have to think about your model and the whole MVVM approach, a good starting point is http://blogs.msdn.com/b/kashiffl/archive/2010/11/14/mvvm-technical-description.aspx.
After you can implement your functionality by different ways, one would be to implement something like the Observer Pattern or you try to use methods like Notify Property-Changed-Events.
Hope i was able to help,
Greetings

ListBox, DataView, And DataTable.RejectChanges()

I have a list box which is binded to a DataView.
<ListBox ItemsSource="{Binding Path=Categories}" DisplayMemberPath="Name"></ListBox>
where Categories is a property to class that inherits the INotifyPropertyChanged interface:
public class EditCategoriesPresenter : INotifyPropertyChanged
{
private DataTable _TableOfCategories;
public DataView Categories { get { return _TableOfCategories.DefaultView; } }
...
}
While all data changes to the underlying DataTable (row inserts and deletes, column value changes) are reflected to list box automatically, when I do a DataTable.RejectChanges() row changes are reflected but not column value changes.
I can understand why this is happening (the DataTable.RejectChanges does not raise any notifications for column value changes) but still cannot find any easy solution to solve it.
I also add the OnPropertyChanged("Categories") after DataTable.RejectChanges() but still no luck.
Any ideas?
Thank you in advance.
when i work with datatables i always use BindingListCollectionView for binding, cause wpf do this anyway implicitly. but now i can use the Refresh() method to refresh my ui binding.
public BindingListCollectionView Categories {get; private set;}
this.Categories = (BindingListCollectionView)CollectionViewSource.GetDefaultView(this._TableOfCategories);
//after reject
this.Categories.Refresh()
nevertheless, what does your ListBox looks like (just the xaml you posted or some datatemplates too)? can you post a screenshot?

Categories