I've been trying iterate through the selected items of a listbox in WPF, with the following code;
try
{
for (int i = 0; i < mylistbox.SelectedItems.Count; i++)
{
ListItem li = (ListItem)mylistbox.SelectedItems[i];
string listitemcontents_str = li.ToString();
}
}
catch(Exception e)
{
// Error appears here
string error = e.ToString();
}
However I receive an invalid cast exception;
System.InvalidCastException: Unable to cast object of type 'mylist' to type 'System.Windows.Documents.ListItem'.
Is there a way around this?
I prefer to do it using data binding:
Sync SelectedItems in a muliselect listbox with a collection in ViewModel
for (int i = 0; i < mylistbox.SelectedItems.Count; i++)
{
List**Box**Item li = (List**Box**Item)mylistbox.SelectedItems[i];
string listitemcontents_str = li.ToString();
}
This should work:
for (int i = 0; i < mylistbox.SelectedItems.Count; i++)
{
var li = mylistbox.SelectedItems[i];
string listitemcontents_str = li.ToString();
}
A way I found was to assign the listbox onto an object then cast this onto a DataRowView. Seems to work and I can get access to the fields inside, by their respective column names.
object selected = mylistbox.SelectedItem;
DataRow row = ((DataRowView)selected).Row;
string thecontents = row["columnname"].ToString().TrimEnd();
You are confusing ListItem with ListBoxItem.
If you do nothing special, a ListBox will create ListBoxItem containers for the data you bind to it. ListItem is used inside FlowDocument and is basically a numbered or bulleted point in a document.
That said, data binding would be better. If you were using data binding, SelectedItems would not be a ListBoxItem but would be your actual data item that was bound. You can cast this to the appropriate type and use it.
The listbox adds it's items as a collection of objects, so it can't cast it to ListItem.
So for your purpose , you can do as following :
for (int i = 0; i < mylistbox.SelectedItems.Count; i++)
{
string listitemcontents_str = mylistbox.SelectedItems[i].ToString();
}
If you really want to use ListBoxItem , please add these items to your listbox e.g.
ListBoxItem li = new ListBoxItem();
li.Content = "Hello";
mylistbox.Items.Add(li);
then you can do what you want without Invalid cast exception:
for (int i = 0; i < mylistbox.SelectedItems.Count; i++)
{
ListBoxItem li = (ListBoxItem)mylistbox.SelectedItems[i];
string s = li.ToString();
}
Related
As an old C++ programmer I am struggling with some C# issues. I want to reduce the redundancy in setting up a ListView. So I tried the code below. I get a null reference error, but I do not understand why. The compiler has no problem with me creating an array of ListViewItems, but I don't see how to use them.
Thanks, Russ
ListViewItem [] items = new ListViewItem [12];
for (int i=0; i < 12; ++i) {
items [i].Text = string.Format ("F{0}", i+1);
}
You're allocating memory for an Array of 12 ListViewItems, but you haven't created the ListViewItem:
Instead, try something like the following:
List<ListViewItem> items = new List<ListViewItem>();
for (int i = 0; i < 12; i++) {
items.Add( //using the List.Add() method to add an item
new ListViewItem
{
Text = string.Format ("F{0}", i+1); //Object Initialization syntax to add an item after construction
});
}
This will create a List (an expandable collection); create a new ListViewItem in a loop, give that ListViewItem the text you want it to have, and then add that item to the List.
It seems that you're receiving the null reference because you're trying to set a property(Text) on something that wasn't initialized (ListViewItem[i]).
Try this:
ListViewItem [] items = new ListViewItem [12];
for (var i = 0; i < items.Length; ++i) {
items[i] = new ListViewItem{Text = string.Format ("F{0}", i+1)};
}
I have a ListView named sandwichToppings which displays various sandwich toppings and allows the user to select multiple. In my controller code, I must capture the selected toppings by their index in the ListView, and send those indices back using an array.
The code which causes me to stumble is visible below. I have not been able to figure out the part which captures one or more toppings to the sandwich (the rest works fine).
void readSandwichSelection()
{
int[] toppings = null;
// One or many toppings were added to the sandwich.
if(toppingsAvailable.SelectedItems.Count > 0)
{
toppings = new int[toppingsAvailable.SelectedItems.Count];
int toppingIndex = 0;
for(int i = 0; i < toppingsAvailable.Items.Count; i++)
{
ListViewItem test = (ListViewItem)toppingsAvailable.Items.ElementAt(i);
if(test.IsSelected == true)
{
toppings[toppingIndex] = i;
toppingIndex++;
}
}
}
// No sandwich topping.
else
{
order.addSandwich(sandwichesAvailable.SelectedIndex + 1);
}
}
Along my journey, I have tried a couple solutions found on Telerik. The first:
foreach (ListViewDataItem item in radListView1.SelectedItems)
{
int example = radListView1.Items.IndexOf(item);
}
The above example fails to work because
ListViewDataItem does not exist.
When replaced by ListViewItem, a run-time error occurs: System.InvalidCastException: 'Unable to cast object of type 'System.String' to type 'Windows.UI.Xaml.Controls.ListViewItem'.'
The second attempted solution:
for (int i = 0; i < radListView1.Items.Count; i++)
{
if (this.radListView1.Items[i].Selected)
{
int example = i;
}
}
This solution cannot work because the .Selected property simply does not exist.
In all my hour of attempted work, I come up with either of these two problems. Either some form of cast exception occurs, or it is impossible to reach the property.
In my example above, I did have success in reaching the isSelected property by making a copy of each list item, and testing whether it had been selected. However, although Visual Studio lets me make the assignment
ListViewItem test = (ListViewItem)toppingsAvailable.Items.ElementAt(i);
this statement cannot run at compile time, causing an error as written previously. Which datatype other than ListViewItem must be used to count over list view items?
toppingsAvailable.SelectedItems will return a List<> of selected items. However, how could I know from this list which list index selected items belong to?
You can try the following code to get the selected toppings's indexes and put the indexes in an array. The indexes will be saved in the ToppingArray.
void readSandwichSelection()
{
int[] ToppingArray = new int[toppingsAvailable.SelectedItems.Count];
for (int i = 0; i < toppingsAvailable.SelectedItems.Count; i++)
{
var selectedIndex = toppingsAvailable.Items.IndexOf(toppingsAvailable.SelectedItems[i]);
ToppingArray[i] = selectedIndex;
}
}
Please try the following. It is Selected rather than IsSelected.
for (int i = 0; i < toppingsAvailable.Items.Count; i++)
{
var test = toppingsAvailable.Items[i];
if (test.Selected)
{
toppings[toppingIndex] = i;
toppingIndex++;
}
}
I have a datagrid, with a number of rows. I want to get the value of cell[0].
In the window form I was using this code:
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
if (dataGridView1.Rows[i].Cells[0].Value == null)
{
//do somthing
}
}
The problem is, I do not know how to get the value of the cell, as this code does not work in WPF.
Like I mentioned in the comments, you need to read more on WPF and bindings that how it works because value which you are trying to get from UI can easily be fetched from underlying data object.
Say you have binded dataGrid to some list ObservableCollection<MyObject> and first column of dataGrid is binded to property Name. You can get value for first cell simply like this:
for (int i = 0; i < dataGridView1.Items.Count; i++)
{
string value = ((MyObject)dataGridView1.Items[0]).Name;
if (String.IsNullOrEmpty(textBlock.Text))
{
// do something.
}
}
That being said, assuming first cell is simple DataGridTextColumn, you can get the value in traditional WinForms way in WPF like this:
for (int i = 0; i < dataGridView1.Items.Count; i++)
{
TextBlock textBlock = dataGridView1.Columns[0]
.GetCellContent(dataGridView1.Items[i]) as TextBlock;
if (textBlock != null)
{
if (String.IsNullOrEmpty(textBlock.Text))
{
// do something.
}
}
}
== is a comparison operator. = is used for assignment:
comboBox3.Text = dataGridView1.Rows[i].Cells[0].Value.ToString();
I have a WinForms application. I've populated my ComboBox with the following code:
cboGridSize.Items.Clear();
for (int i = 2; i <= 12; i++)
cboGridSize.Items.Add(new KeyValuePair<string,int>(i.ToString(), i));
cboGridSize.SelectedValue = 4;
However, the last line has absolutely no effect. The ComboBox appears with no items selected.
So I was doing some debugging and noticed some odd things. The following image is from the watch window after setting cboGridSize.SelectedIndex to 0.
Watch Window http://www.softcircuits.com/Client/debugwin.jpg
Even though the SelectedItem property contains exactly what I would expect, SelectedValue is still null. Although the documentation for SelectedValue is pathetic, I understood it would contain the value of the selected item (SelectedItem). Instead, the two properties seem completely unrelated. Can anyone see what I have wrong?
As you can see, I have the ValueMember property set. And the DropDownStyle property is set to DropDownList.
EDIT:
Once Nikolay Khil set me straight on the issue here (why the docs for SelectedValue don't do that escapes me), I decided to simply write my own code to accomplish the same task. I'm posting it here in case anyone is interested.
static class ComboBoxHelper
{
public static void LookupAndSetValue(this ComboBox combobox, object value)
{
if (combobox.Items.Count > 0)
{
for (int i = 0; i < combobox.Items.Count; i++)
{
object item = combobox.Items[i];
object thisValue = item.GetType().GetProperty(combobox.ValueMember).GetValue(item);
if (thisValue != null && thisValue.Equals(value))
{
combobox.SelectedIndex = i;
return;
}
}
// Select first item if requested item was not found
combobox.SelectedIndex = 0;
}
}
}
This is implemented as an extension method so I simply change my original code as follows:
cboGridSize.Items.Clear();
for (int i = 2; i <= 12; i++)
cboGridSize.Items.Add(new KeyValuePair<string,int>(i.ToString(), i));
cboGridSize.LookupAndSetValue(4);
Both ValueMember and DisplayMember properties are used only if DataSource property is defined.
So, you should re-write your code as follows:
private readonly BindingList<KeyValuePair<string, int>> m_items =
new BindingList<KeyValuePair<string, int>>();
public YourForm()
{
InitializeComponent();
cboGridSize.DisplayMember = "Key";
cboGridSize.ValueMember = "Value";
cboGridSize.DataSource = m_items;
for (int i = 2; i <= 12; i++)
m_items.Add(new KeyValuePair<string,int>(i.ToString(), i));
cboGridSize.SelectedValue = 4;
}
Links:
BindingList class
ObservableCollection class
INotifyCollectionChanged Interface
This does not answer the OP however...the ComboBox SelectedValue must be an integer type.
If you have a short or byte var that holds the value that will set the SelectedValue, it won't work - you will have null/nothing value.
Use an integer.
I know this is an old question but I've just come across this problem myself. I solved with the following - it's slightly hacky but it works:
if(newVal != null)
{
MyComboBox.SelectedValue = newVal;
}
else
{
MyComboBox.SelectedIndex = 0; // the 'None Selected' item
}
Hope this helps someone.
u can set SelectedValue first, and then set Datasource and others
I'm trying to find the selected Item in an aspx ListView that is on a separate page, then switch the page and select the item. I have the value property of the ListViewItem I am looking for, but cannot seem to get it to work. Here is what I tried:
for (int i = 0; i < lvProject.Items.Count; i++)
{
if (((Label)lvProject.Items[i].FindControl("Project_IDLabel")).Text == project.ToString())
{
lvProject.SelectItem(i);
break;
}
}
So lvProject is my list view. The project Variable is an Int64 which represents the UID of my Project. This is also the Value of my ListViewItems. The problem with the code above is that when paging is enabled, and the item is on a different page this will not work because the listView.Items.Count is set to the # of Items on the current page only.
My goal is to find the item, set the listview to display the correct page, and finally select the item. You would figure that I could just set the SelectedValue property, but this is not that simple as it is read only. Any ideas would help greatly, thanks in advance.
--Roman
In order to get the total record count from the object data source, you should use the Selected event as follows:
protected void ObjectDataSource1_Selected(object sender, ObjectDataSourceStatusEventArgs e)
{
// Get total count from the ObjectDataSource
DataTable dt = e.ReturnValue as DataTable;
if (dt != null) recordCount = dt.Rows.Count; // recordCount being declared outside the method
}
You would then be able to search for the item as follows:
for (int i = 0; i < recordCount; i++)
{
Label lblItem = (Label)lvProject.Items[i].FindControl("IdLabel");
if (lblItem.Text.Equals(itemToSearch))
{
lvProject.SelectedIndex = i;
break;
}
}
Hope it helps!
How do you bind ListView Items?
If you are using database level paging (stored procedure, query) - you should do search in the same way - using database query/stored procedure by passing a search criteria.
If you are bind ListView Items to a collection of items which are provided by a business/data layer - you have to create search method on layer which provides items so this method will be able to loop through the items.
You should set the SelectedIndex property to i
for (int i = 0; i < lvProject.Items.Count; i++)
{
if (((Label)lvProject.Items[i].FindControl("Project_IDLabel")).Text == project.ToString())
{
lvProject.SelectedIndex = i;
break;
}
}