Programmatically set ComboBox SelectedItem in WPF (3.5sp1) - wpf

I have been confused while setting SelectedItem programmaticaly in wpf applications with Net Framework 3.5 sp1 installed. I have carefully read about hundred posts \topics but still confused((
My xaml:
<ComboBox name="cbTheme">
<ComboBoxItem>Sunrise theme</ComboBoxItem>
<ComboBoxItem>Sunset theme</ComboBoxItem>
</ComboBox>
If I add IsSelected="True" property in one of the items - it's dosn't sets this item selected. WHY ?
And i was try different in code and still can't set selected item:
cbTheme.SelectedItem=cbTheme.Items.GetItemAt(1); //dosn't work
cbTheme.Text = "Sunrise theme"; //dosn't work
cbTheme.Text = cbTheme.Items.GetItemAt(1).ToString();//dosn't work
cbTheme.SelectedValue = ...//dosn't work
cbTheme.SelectedValuePath = .. //dosn't work
//and even this dosn't work:
ComboBoxItem selcbi = (ComboBoxItem)cbTheme.Items.GetItemAt(1);//or selcbi = new ComboBoxItem
cbTheme.SelectedItem = selcbi;
The SelectedItem is not readonly property, so why it wan't work?
I think thats should be a Microsoft's problems, not my. Or I have missed something??? I have try playing with ListBox, and all work fine with same code, I can set selections, get selections and so on.... So what can I do with ComboBox ? Maybe some tricks ???

To select any item in the ComboBox and to set it as default item selected just use the below line:
combobox.SelectedIndex = 0; //index should be the index of item which you want to be selected

If i add the combobox and items programmatically, this works for me:
ComboBox newCombo = new ComboBox();
ComboBoxItem newitem = new ComboBoxItem();
newitem.Content = "test 1";
newCombo.Items.Add(newitem);
newitem = new ComboBoxItem();
newitem.Content = "test 2";
newCombo.Items.Add(newitem);
newitem = new ComboBoxItem();
newitem.Content = "test 3";
newCombo.Items.Add(newitem);
newCombo.SelectedItem = ((ComboBoxItem)newCombo.Items[1]);
newCombo.Text = ((ComboBoxItem)newCombo.Items[1]).Content.ToString();
newStack.Children.Add(newCombo);
It also works if it set the ItemSource property programmatically, then set the text to the selected value.

Create a public property in your viewmodel for the theme list and one for the selected item:
private IEnumerable<string> _themeList;
public IEnumerable<string> ThemeList
{
get { return _themeList; }
set
{
_themeList = value;
PropertyChangedEvent.Notify(this, "ThemeList");
}
}
private string _selectedItem;
public string SelectedItem
{
get { return _selectedItem; }
set
{
_selectedItem = value;
PropertyChangedEvent.Notify(this,"SelectedItem");
}
}
bind your combobox in xaml to the properties like this:
<ComboBox
Name="cbTheme"
ItemsSource="{Binding ThemeList}"
SelectedItem="{Binding SelectedItem}">
</ComboBox>
now all you do is add items to the ThemeList to populate the combobox. To select an item in the list, set the selected property to the text of the item you want selected like this:
var tmpList = new List<string>();
tmpList.Add("Sunrise theme");
tmpList.Add("Sunset theme");
_viewModel.ThemeList = tmpList;
_viewModel.SelectedItem = "Sunset theme";
or try setting the selected item to the string value of the item you want selected in your own code if you want to use the code you currently have - not sure if it will work but you can try.

If you know the index of the item you want to set, in this case it looks like you are trying to set index 1, you simply do:
cbTheme.SelectedIndex = 1;
I found that when you don't know the index, that's when you have the real issue. I know this goes beyond the original question, but for Googlers on that count that want to know how to set the item when the index isn't known but the value you want to display IS known, if you are filling your dropdown with an ItemSource from a DataTable, for example, you can get that index by doing this:
int matchedIndex = 0;
if (dt != null & dt.Rows != null)
{
if (dt.Rows.Count > 0)
{
foreach (DataRow dr in dt.Rows)
{
string myRowValue = dr["SOME_COLUMN"] != null ? dr["SOME_COLUMN"].ToString() : String.Empty;
if (myRowValue == "Value I Want To Set")
break;
else
matchedIndex++;
}
}
}
And then you do simply do cbTheme.SelectedIndex = matchedIndex;.
A similar iteration of ComboBoxItem items instead of DataRow rows could yield a similar result, if the ComboBox was filled how the OP shows, instead.

Is the ComboBox data bound?
If so you are probably better to do it through Binding rather than code ....
See this question ... WPF ListView Programmatically Select Item
Maybe create a new SelectableObject {Text = "Abc Theme", IsCurrentlySelected = True}
Bind a collection of SelectableObjects to the ComboBox.
Essentially setting the IsCurrentlySelected property in the model and having UI update from the Model.

Acording Answer 4
If you already add the Items in the Item source.
Fire the PropertyChangedEvent of the selectet Value.
tmpList.Add("Sunrise theme");
tmpList.Add("Sunset theme");
PropertyChangedEvent.Notify(this,"SelectedItem");

Related

Populating a Combobox with LinqToSql and choose an item from it

Here's code to populate a combobox with Linq-to-SQL:
private void FillEmbCB()
{
DataClasses1DataContext dc = new DataClasses1DataContext();
var emb = from e in dc.EMBALLAGES
select new
{
e.EMB_CODE,
e.EMB_LIB
};
Emb1CB.ItemsSource = emb;
Emb1CB.SelectedValuePath = "EMB_CODE";
Emb1CB.DisplayMemberPath = "EMB_LIB";
Emb1CB.SelectedItem = "HOUSSE PROTEC PALETTE"; // Nothing appears in the combobox
dc.Dispose();
}
At the end of that code, I want to choose an item from the combobox I've just populated, and show it in the combobox, but nothing appears, the combobox is always empty.
Here's my Xaml markup:
<ComboBox x:Name="Emb1CB" Width="200" FontSize="12"
SelectionChanged="Emb1CB_SelectionChanged"/>
SelectedValuePath is used for data binding (which you should be doing instead of manipulating the GUI directly like this, but that's another discussion). If you want to set SelectedItem yourself then you need to set the value to the parent object that contains the value, e.g.:
using System.Linq;
Emb1CB.SelectedItem = emb.FirstOrDefault(x => x.EMB_CODE == "HOUSSE PROTEC PALETTE");

WPF ComboBox's SelectedIndex doesn't change after setting its IsTextSearchEnabled to false

Let's say I have a ComboBox named comboBox.
I want to disable ComboBox's auto complete feature.
At first I thought that everything I need to do is setting its IsTextSearchEnabled to false as following
comboBox.IsTextSearchEnabled = false;
But it seems doing this cause some unexpected side effects.
When IsTextSearchEnabled = true (which is default with combobox) if you try to set a value for ComboBox's Text, the combobox will find corresponding index in its ItemsSource and update the its SelectedIndex accordingly.
List<string> lst = new List<string>();
lst.Add("1");
lst.Add("2");
lst.Add("3");
lst.Add("4");
lst.Add("5");
MessageBox.Show(comboBox.SelectedIndex.ToString()); // -1
comboBox.ItemsSource = lst;
comboBox.Text = "3";
MessageBox.Show(comboBox.SelectedIndex.ToString()); // 2
Now when I tried to set IsTextSearchEnabled = false, the ComboBox's SelectedIndex doesn't get updated when its Text changes.
List<string> lst = new List<string>();
lst.Add("1");
lst.Add("2");
lst.Add("3");
lst.Add("4");
lst.Add("5");
MessageBox.Show(comboBox.SelectedIndex.ToString()); // -1
comboBox.IsTextSearchEnabled = false;
comboBox.ItemsSource = lst;
comboBox.Text = "3";
MessageBox.Show(comboBox.SelectedIndex.ToString()); // -1
I wonder if there is a way to achieve both (i.e disabling Auto Complete feature and still have ComboBox update its SelectedIndex automatically when its Text is changed)
There are several ways to reach it. In your case with strings it's enough to set not the Text property, but SelectedValue:
List<string> lst = new List<string>();
lst.Add("1");
lst.Add("2");
lst.Add("3");
lst.Add("4");
lst.Add("5");
MessageBox.Show(comboBox.SelectedIndex.ToString()); // -1
comboBox.IsTextSearchEnabled = false;
comboBox.ItemsSource = lst;
comboBox.SelectedValue = "3";
MessageBox.Show(comboBox.SelectedIndex.ToString()); // 2
If you have more complex data type as string, then you can set also SelectedValuePath or search it by yourself in ItemsSource in event handler for TextInput and set the ´SelectedItem´.

How do I set values for the entries in a Windows Forms ComboBox?

I want to have a drop down list with 12 choices.
I found that ComboBox is what I need (if there is a better control kindly tell me).
I dragged and drop a combo box into a panel using VS2012 and then clicked on the left arrow that appears on the combo box. The following wizard shows:
As you can see, I am just able to type the name of the choice but not the value of it.
My question is how to get the value of these choices?
What I have tried
I built an array with the same length as the choices, so when the user selects any choice, I get the position of that choice and get the value from that array.
Is there a better way?
You need to use a datatable and then select the value from that.
eg)
DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Description", typeof(string));
dt.Load(reader);
//Setting Values
combobox.ValueMember = "ID";
combobox.DisplayMember = "Description";
combobox.SelectedValue = "ID";
combobox.DataSource = dt;
You can then populate your datatable using:
dt.Rows.Add("1","ComboxDisplay");
Here, the DisplayMember(The dropdown list items) are the Descriptions and the Value is the ID.
You need to include a 'SelectedIndexChanged' Event on your combobox (If using VS then double click the control in Design Mode) to get the new values. Something like:
private void ComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
int ID = Combobox.ValueMember;
string Description = ComboBox.DisplayMember.ToString();
}
You can then use the variables in the rest of your code.
You cannot use the wizard to store values and text. To store DisplayText/Value pair the combobox needs to be connected to some data.
public class ComboboxItem
{
public string DisplayText { get; set; }
public int Value { get; set; }
}
There are two properties on the combobox - DisplayMember and ValueMember. We use these to tell the combobox that - show whats in DisplayMember and the actual value is in ValueMember.
private void DataBind()
{
comboBox1.DisplayMember = "DisplayText";
comboBox1.ValueMember = "Value";
ComboboxItem item = new ComboboxItem();
item.DisplayText = "Item1";
item.Value = 1;
comboBox1.Items.Add(item);
}
To get the value -
int selectedValue = (int)comboBox1.SelectedValue;

Under SelectionChanged read out the underlying data from a List

Im busy with my app and i walked in some problems when i click on a photo in my listbox PhotoFeed.
I got 1 List<> with in it the strings UrlTumb and UrlFull.
I got 1 ListBox with in it a WrapPanel filled with images wich i set the Image.Source from my UrlTumb.
What my problem is when i click on a photo in my listbox i want to navigate to a new page and display there the original image (UrlFull) now i can only get my UrlTumb from my Image.Source but i want my UrlFull which is stored in the List. Now is my question how do i obtain the UrlFull. So how can i back trace which item i clicked and get the UrlFull from that item so i can send it with my NavigationService.Navigate
I can do it on an dirty way and create an invisible textblock besides the image in my ListBox and put the UrlFull in there but i would like to do it in a proper way
So what do i place in the ????? spot in this line
NavigationService.Navigate(new Uri("/PhotoInfo.xaml?urlfull={0}", ????? , UriKind.Relative));
Greetings Cn
There are multiple options:
Use selected item's index listBox.SelectedIndex to get the index
of the selected property which will correspond to the index in your
source (it might not if you filter the collection using collection
source, but I think that is not the case)
Use selected item listBox.SelectedItem this will return the
SelectedItem which will contain your object. (Note, that if your
selection mode set to multiple, this will return only the firstly
selected item)
Use SelectemItems. It will allow you to get an array of selected
items (Note: this should be normally used only when your list's
selection mode is set to multiple)
Use SelectedValue, which will contain the value of the SelectedItem
(this will save you and extra step.
Use arguments of the Selection changed event AddedItems.
Bellow is the code snippet of 3 options above. x, y, z will all be your selected names (e.g. "Mike")
XAML:
<ListBox x:Name="lb"
ItemsSource="{Binding Names}"
SelectionChanged="NameChanged" />
Code behind:
public class Person
{
public string Name { get; set; }
public override string ToString()
{
return Name;
}
}
private List<Person> people = new List<Person>
{
new Person{Name = "Lewis"},
new Person{Name = "Peter"},
new Person{Name = "Brian"}
};
public List<Person> People
{
get
{
return this.people;
}
set
{
this.people = value;
}
}
private void NameChanged(object sender, SelectionChangedEventArgs e)
{
var x = this.people[lb.SelectedIndex];
var y = lb.SelectedItem;
var z = lb.SelectedItems[0];
var h = lb.SelectedValue;
var u = e.AddedItems[0];
var person = e.AddedItems[0] as Person;
if (person != null)
{
var result = person.Name;
}
}
For the differences between SelectedValue and SelectedItem refer here SelectedItem vs SelectedValue

Set DisplayMemberPath and SelectedValue in WPF with Code

I have a DataTable that is coming from a Web Service, which I need to bind to a ComboBox. I have not grokked doing binding in XAML yet so this question is about binding in code instead. So far I have tried
cboManager.DataContext = Slurp.DistrictManagerSelect().DefaultView;
cboManager.DisplayMemberPath = "Name";
cboManager.SelectedValuePath = "NameListId";
cboManager.SetBinding(ComboBox.ItemsSourceProperty, new Binding());
And I have tried
DataTable tbl = new DataTable();
tbl = Slurp.DistrictManagerSelect();
cboManager.ItemsSource = ((IListSource)tbl).GetList();
cboManager.DisplayMemberPath = "[Name]";
cboManager.SelectedValuePath = "[NameListId]";
DataContext = this;
In both cases I get the list of managers to show but when I select from the ComboBox I get [Name] and [NameListId] and not the values I am expecting. What am I doing wrong (other than not using XAML's DataBinding)?
Edit added after answers to my original post came in.
So (based on Rachel's response) try number three looks like this:
using (DataTable tbl = Slurp.DistrictManagerSelect())
{
List<ManagerList> list = new List<ManagerList>();
foreach (var row in tbl.Rows)
{
list.Add(new ManagerList
{
NameListId = (int)row[0],
Name = row[1].ToString()
});
}
}
Assuming I am doing what she meant the correct way I am no getting this error Cannot apply indexing with [] to an expression of type 'object'
Have you tried to just bind to the DataTable directly? Do you have columns Name and NameListId? Leave off the DataContext (you already assigned the ItemsSource).
DataTable tbl = Slurp.DistrictManagerSelect();
cboManager.ItemsSource = tbl;
cboManager.DisplayMemberPath = "Name";
cboManager.SelectedValuePath = "NameListId";
When you cast to the IListSource I suspect it is combining all the columns. If you want to bind to a list then you need to create items that have properties Name and NameListID.
I think that's because your ItemsSource is a DataTable, so each ComboBoxItem contains a DataContext of a DataRow, and the DataRow class doesn't have properties called Name or NameListId
Basically, you're trying to tell the ComboBox to display DataRow.Name, and set the value to DataRow.NameListId, both of which are not valid properties.
I usually prefer to parse data into objects, and bind the ItemsSource a List<MyObject> or ObservableCollection<MyObject>
foreach(DataRow row in tbl.Rows)
list.Add(new MyObject { Name = row[0].ToString(), NameListId = (int)row[1] });
cboManager.ItemsSource = list;

Resources