Let's say you have one Listbox in WPF with items such as 1,2,3,4,5 etc. How do you make another Listbox, right next to first one, that shows its items according to selection in the first Listbox? So if you select "item 2" in Listbox you'd get 2A, 2B,2C etc in Listbox2, if you select "item 3" you'd get 3A, 3B, 3C etc in Listbox3
Can't embed the picture yet but here's the example of what i need
There is an example of how to implement such cascading ComboBoxes according to the recommended MVVM design pattern available here: https://blog.magnusmontin.net/2013/06/17/cascading-comboboxes-in-wpf-using-mvvm/
You could bind the SelectedItem property of the first ListBox to a source property of your view model. In the setter of this one you then set another collection property that you bind the ItemsSource property of the second ListBox to, e.g.:
<ListBox ItemsSource="{Binding Numbers}" SelectedItem="{Binding SelectedNumber}" />
<ListBox ItemsSource="{Binding SubNumbers}" />
private object _selectedNumber;
public object SelectedNumber
{
get { return _selectedNumber; }
set
{
_selectedNumber = value;
NotifyPropertyChanged();
//set items
SubNumbers = new List<string> { "3A", "3B", "..." };
NotifyPropertyChanged("SubNumbers");
}
}
Make sure that your view model class implements the INotifyPropertyChanged interface and raises change notifications for this to work: https://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.110).aspx
Alternatively, if your model classes are defined in such a way that each item in the first ListBox has a collection property that returns its related items, you could bind the second ListBox directly to a property of the SelectedItem in the first one:
<ListBox x:Name="lb1" ItemsSource="{Binding Numbers}"/>
<ListBox x:Name="lb2" ItemsSource="{Binding SelectedItem.SubProperty, ElementName=lb1}" />
Related
I have the following observable collection called SalesOrderCollection
private static ObservableCollection<SalesOrder> _salesOrderCollection = new ObservableCollection<SalesOrder>();
public static ObservableCollection<SalesOrder> SalesOrderCollection
{
get { return _salesOrderCollection; }
set
{
_salesOrderCollection = value;
}
}
I am assigning values like this:
SalesOrder order = new SalesOrder();
order.ItemSubTotal = 234;
order.TotalTaxes = 12;
order.TOTAL = 12345;
SalesOrderCollection.Add(order);
In the view, I am setting it like this to the label:
<Label Content="{Binding Path=TOTAL, UpdateSourceTrigger =PropertyChanged}"/>
However the label is empty. Any suggestions as to what I am doing wrong here ?
First of all, you are binding incorrectly - the label should not be bound to a specific item in a collection. Instead you should use a list control to show the contents of the ObesrvableCollection, then bind the selected item in the list control to a property on the viewmodel. Then the label should also be bound to the same property which contains the selected object.
If you insist on doing indexed binding to a specific item in the ObservableCollection then this syntax should do it for you:
<Label Content="{Binding Path=SalesOrderCollection[0].TOTAL}"/>
Here is an example.
Just another pointer: I'm not sure why you've made your SalesOrderCollection property static - this looks like the start of some potentially smelly code.
I am having trouble assigning the a combobox item by using an enum value that the combobox source is assigned to.
The XAML
<ComboBox HorizontalAlignment="Left"
x:Name="cmbName"
VerticalAlignment="Top"
Width="120" Margin="79,48,0,0">
<ComboBox.ItemsSource>
<CompositeCollection>
<ListBoxItem Content="Please Select"/>
<CollectionContainer Collection="{Binding Source={StaticResource Enum}}" />
</CompositeCollection>
</ComboBox.ItemsSource>
</ComboBox>
The C# that is trying to set the combobox to an item in the enum
// The problem, the assignment doesn't work.
cmbName.SelectedItem = Enum.value;
I can only set a item by using the combobox SelectedIndex
cmbName.SelectedIndex = 2;
But this is hardcoding the index so if the enum changes, so will the value.
So how can I set the combobox by the enum value?
Thanks
It's very hard to tell what your problem is because you haven't fully documented your scenario. As such, all that I can do is to show you how to do what you want. As I prefer to work with properties, I won't be using any Resources for this example, but I'm sure that you'll still be able to relate this solution to your problem.
So, first we have a test enum and some properties and some initialisation:
public enum TestEnum
{
None, One, Two, Three
}
private TestEnum enumInstance = TestEnum.None;
public TestEnum EnumInstance
{
get { return enumInstance; }
set { enumInstance = value; NotifyPropertyChanged("EnumInstance"); }
}
private ObservableCollection<TestEnum> enumCollection = new ObservableCollection<TestEnum>() { TestEnum.None, TestEnum.One, TestEnum.Two, TestEnum.Three };
public ObservableCollection<TestEnum> EnumCollection
{
get { return enumCollection; }
set { enumCollection = value; NotifyPropertyChanged("EnumCollection"); }
}
...
EnumCollection.Add(TestEnum.One);
EnumCollection.Add(TestEnum.Two);
EnumCollection.Add(TestEnum.Three);
EnumInstance = TestEnum.Three;
Then we have a ComboBox:
<ComboBox Name="ComboBox" ItemsSource="{Binding EnumCollection}"
SelectedItem="{Binding EnumInstance}" />
If you run the application, then at this point the selected ComboBoxItem should read Three. Because the ComboBox.SelectedItem is data bound to the EnumInstance property, setting...:
EnumInstance = TestEnum.Two;
... is roughly the same as:
ComboBox.SelectedItem = TestEnum.Two;
Both of these would select the Two value in the ComboBox. However, note this example:
EnumInstance = TestEnum.None;
Setting either the EnumInstance or the ComboBox.SelectedItem property to TestEnum.None would have no effect in the UI because there is no TestEnum.None value in the data bound collection.
I apologise that my answer was descriptive enough, however, the reason why I haven't set my enum as a property as Sheridan has described below is that I need an extra string value in my combo which you can see is "Please Select" and unfortunately, I cannot put this in the enum.
But Sheridan's method and logic is the way to go if you want to do this.
However, for my problem, I simply just used
ComboBox.SelectedValue = Enum.Value.ToString();
Thanks
The Scenario
I have a UserControl which contains a couple of controls, one of which is a ComboBox. The UserControl is conatined with a Page.
The UserControl exposes a couple of dependency properties to allow the Items and SelectedValue of the ComboBox to be accessed. These are defined as follows:
public static readonly DependencyProperty SelectedValueProperty = DependencyProperty.Register("SelectedValue", typeof(int?), typeof(CustomComboBox), new FrameworkPropertyMetadata((int?)null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public int? SelectedValue
{
get { return (int?)this.GetValue(SelectedValueProperty); }
set { this.SetValue(SelectedValueProperty, value); }
}
public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof(List<ComboItem>), typeof(CustomComboBox), new FrameworkPropertyMetadata((List<ComboItem>)new List<ComboItem>(), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public List<ComboItem> Items
{
get { return (List<ComboItem>)this.GetValue(ItemsProperty); }
set { this.SetValue(ItemsProperty, value); }
}
These are binded to the ComboBox control as follows:
<ComboBox ItemsSource="{Binding Path=Items, ElementName=ThisControl}" DisplayMemberPath="Text" SelectedValuePath="ID" SelectedValue="{Binding Path=SelectedValue, ElementName=ThisControl, UpdateSourceTrigger=PropertyChanged}" />
Where the UserControl is named "ThisControl".
Also, in the above, ComboItem is a class which contains the definitions for each item, namely two properties called ID and Text. The idea here is that ID is the key that is stored in the database, and Text is the user friendly value that is displayed in the list.
When the Page containing the UserControl is created (using the Constructor), the ComboBox items list is populated with the following code:
MyComboBox.Items.Clear();
MyComboBox.Items.Add(new ComboItem() { ID = 1, Text = "One" });
MyComboBox.Items.Add(new ComboItem() { ID = 2, Text = "Two" });
Finally, the SelectedValue is binded to a class property via XML like so:
<c:CustomComboBox x:Name="MyComboBox" SelectedValue="{Binding Path=MyClassInstance.ItemID}" />
where the property ItemID is of type int. It is important to note that the class instance is set after the combo box items are populated.
The Problem
When the page is first shown, the initial selected value is not set correctly - it is an empty item selection. I can assure that the ItemID property is already set to a valid value (i.e. 1).
When an item is selected from the ComboBox, the binding does successfully set the ItemID property, and is correctly persisted to the database upon a 'save' function.
One strange behavior, which may help to identity the problem, is that if the window containing the Page is closed, and then re-opened. The ComboBox does get th correct initial value - and that is regardless of the ComboBox being set on first attempt, or otherwise.
So, the question is: Why is the initial value not shown the first time the page is displayed?
OK, I was doing some refactoring to improve how I populate the ComboBox Items and I seem to have stumbled across the solution...
The problem seems to be related to the following piece of code that populates the list items:
MyComboBox.Items.Clear();
MyComboBox.Items.Add(new ComboItem() { ID = 1, Text = "One" });
MyComboBox.Items.Add(new ComboItem() { ID = 2, Text = "Two" });
The solution is to directly set the Items property, rather than to clear it and populate it:
MyComboBox.Items = GetMyList();
Where GetMyList() is returning a List<ComboItem> type.
Is it possible to insert values from combobox to specific column in database?
For example if i have combobox with items: item1, item2, item3 and I want to bind them to some column: column1, what I want to manage is this: if item1 is selected, when I click on button, I want to insert value of that item in the column1, otherwise if selected item is item2 then I want value of item2 to be inserted in column1, etc...
Now I know that the question is not really well written, but I just want to know if this is possible to do.
I've been Googling for this type of problem but I couldn't find the solution. I know how to make column records to be inserted into combobox items list but don't know the way to do the opposite.
Also would like to say that I have this problem in my WPF/WCF/MVVM application, so I would like to know if this is possible (and how) to solve it that way.
This solution is based on MVVM pattern .
Bind the Selected item of combo box control to some property in View model.
So your view should look like
<ComboBox ItemsSource="{Binding SomeItems,UpdateSourceTrigger=PropertyChanged,NotifyOnSourceUpdated=True}" SelectedValue="{Binding SelectedItemBinding,UpdateSourceTrigger=PropertyChanged,NotifyOnSourceUpdated=True}" />
<Button Command={Binding ButtonClickCommand} ..../>
so once the Button is clicked you will get the RelayCommand handle in viewmodel and you can have a logic there to Get the selected item and use the value to insert into the column. Your view model should look like ,
public class ViewModel : //implement notify property changed and ICommand
{
public RelayCommand ButtonClickCommand
{
get new RelayCommand(EventHandlerToBeCalled);
}
public string SelectedItemBinding
{
get;
set
{
//notify property changed.
}
}
//method called when button is clicked.
private void EventHandlerToBeCalled()
{
//here set the SelectedItemBinding to a column.
}
}
ofc you can. On the button click event you can just get the selected value of the combobox and save it.
var selectedItem = ComboBoxName.SelectedItem;
But if you have binded the combobox with objects then you can cast it.
var selectedItem = ComboBoxName.SelectedItem as (objecttypehere)
Update
I missed that you used MVVM. Then in the view you can use bind the combobox with selected item.
<ComboBox ItemsSource="{Binding Items}" SelectedItem="{Binding TheSelectedItem}">
//Itemtemplates.
</ComboBox>
In the viewModel just acces the property you binded with the selecteditem in my test case "TheSelectedItem" property.
Save it!
in combobox you can store values with prefix (col1_12, col2_24 etc)
on button click you should parse value: separate it on prefix and original value
so you can write value to needed column:
switch (prefix) {
case "col1" : table.column1 = value; break;
case "col2" : table.column2 = value; break;
// etc
}
I am having a combobox and the data is assigned dynamically as follows
<combobox
name="clientbox"
itemsource={Binding},
displaymemberpath="ClientName"
selectedvaluepath="clientid" />
I am loading the client details from DB and setting them to a listbox and assigning to the combobox as follows.
clientbox.DataContext = <list>
I am able to see the data in the combox after run. This will select the 0th item, but I want to default select different item. How to do this?
clientbox.SelectedItem = ((ComboBoxItem)clientbox.Items[1]);
clientbox.Text = ((ComboBoxItem)clientbox.Items[1]).Content.ToString();
There are several possibilities:
Code-behind:
// Setting the 0-based index
clientBox.SelectedIndex = 1;
// Setting the item
clientBox.SelectedItem = activeClient;
// Setting the value (explanation follows..)
clientBox.SelectedValue = activeClientValue
Using the SelectedValue property you can define a property of the item which is used to fill the ComboBox. An example: You fill the ComboBox with items of a class Client which has the properties Id, Name and so on. If you select an item, the SelectedItem property will be an instance of the class Client. By setting the SelectedValuePath property of the ComboBox to Id the SelectedValue will always just contain the id of the selected client.
Binding:
Of course you can always use bindings.
<ComboBox x:Name="clientBox"
ItemsSource={Binding ClientList}, DisplayMemberPath = "Name"
SelectedValuePath="Id"
SelectedValue={Binding ActiveClient} />