listview- System.ArgumentOutOfRangeException - c#

I have a listview which has 7 columns. I want to add information on each column, but when it reaches the subitem 2 from the listView I get a System.ArgumentOutOfRangeException even though I have that subitem.
Any idea why I get this error? I've tried to search for it but I haven't found a similar case.
This is the part of the code where I get that error:
if (seen == true)
listView1.SelectedItems[0].SubItems[2].Tag = "Seen";
else
listView1.SelectedItems[0].SubItems[2].Tag = "Not Seen";

You probably do not have all those SubItems in each item.
Or maybe nothing is selected? (Note that the SelectionChanged event gets called when an Item is unselected as well!)
Note that every Item in a ListView can have its own number of SubItems, no matter how many Columns you have created. These only provide a space to display the data, not slots you can access without creating SubItems !
Therefore we must test it before we access it! In other words: The ListView structure is not a 2d array but a jagged array!
This could be a possible check..:
if ( listView1.SelectedItems[0].Count > 0 &&
listView1.SelectedItems[0].SubItems.Count > 2 )
listView1.SelectedItems[0].SubItems[2].Tag = seen ? "Seen" : "Not Seen";
..but you know your code better and may well find a nicer way of doing the necessary tests..
Just do not rely on the number of SubItems being equal to the number of Columns. They are not related at all and either may be greater in each Item!

Related

GridView and VariableSizedWrapGrid templating windows store app

I'm writing a windows store app, the main page is a GridView of grouped items.
I already managed to get the templates of the different tiles of the GridView,
but the problem is as follows:
I have bound the ItemsSource to my viewModel's collection that holds 12 items.
there is 2 different problems:
First, how can I make the GridView to always not show the last one or two items, in that way that the there is always a missing tile or two as shown in the picture, although there is "room" for more items in the bounded collection.
Second, I'm using an ItemTemplateSelector for different templates for the items based on an index.
my design is that in every last item I need to select a template without an image(for the example).
How can I get the last visible item in the GridView?
This is my code to create the different tile sizes:
protected override void PrepareContainerForItemOverride(Windows.UI.Xaml.DependencyObject element, object item)
{
try
{
IIndexable viewModel = item as IIndexable;
element.SetValue(Windows.UI.Xaml.Controls.VariableSizedWrapGrid.ColumnSpanProperty, viewModel.Index == 0 ? 2 : 1);
element.SetValue(Windows.UI.Xaml.Controls.VariableSizedWrapGrid.RowSpanProperty, viewModel.Index == 0 ? 2 : 1);
}
catch
{
element.SetValue(Windows.UI.Xaml.Controls.VariableSizedWrapGrid.ColumnSpanProperty, 1);
element.SetValue(Windows.UI.Xaml.Controls.VariableSizedWrapGrid.RowSpanProperty, 1);
}
finally
{
base.PrepareContainerForItemOverride(element, item);
}
}
Thanks.
In order to do that, you'll either have to write your own control or you can have your viewmodel (which should store your itemssource) return a subset of the items.
If you do write your own control, you'll want to override the ArrangeOverride and MeasureOverride methods. You'll then be able to create a dependency property of something like "MaximumColumns". Your Arrange and Measure methods can then determine whether or not to add a child to the tree based on if there's enough room. I suggest creating a two-dimensional array of bools to keep track of which cells are occupied, then having a "Fit" function that attempts to find if there is room for the object you are adding.
For returning the subset of items, you can either have your viewmodel calculate how much space each one will take and return a new collection of the proper items, or you can just hard limit it to a given value.

Problems with selected indices in listview

I have an arraylist which contain objects of my own class. I want to fetch the object from the array list which has the index = selectedindex of listview.
I tried this :
TrackInformation t=(TrackInformation) SongList[listView1.SelectedIndices[0]];
TrackInformation is my class and SongList is an ArrayList of type TrackInformation.
listview1 does not allow multiple indices selection so I want the first element of the SelectedIndices collection.
I am getting ArgumentOutOfRangeException and it says value of '0' is not valid for 'index'.
Put this line before your code -
if(listView1.SelectedIndices.Count > 0)
{
TrackInformation t=(TrackInformation) SongList[listView1.SelectedIndices[0]];
}
The ListView.SelectedIndexChanged event has a quirk that bombs your code. When you start your program, no item is selected. Click an item and SelectedIndexChanged fires, no problem. Now click another item and the event fires twice. First to let you know, unhelpfully, that the first item is unselected. Then again to tell you that the new item is selected. That first event is going to make you index an empty array, kaboom. RV1987's snippet prevents this.
The error is because listView1.SelectedIndices is empty, do you have a row selected?
you probable want to wrap in a test
ListView.SelectedIndexCollection selected=listView1.SelectedIndicies;
if (selected.Count==0) {
// code for no items selected
} else {
TrackInformation t=(TrackInformation) SongList[selected[0]];
// rest of code to deal with t
}

Efficient method of changing columns in a DataGridView

Hello I have an empty DatagridView that is disabled until I start adding rows to it. I have a combo box that has two selectable options that is going to control what information is going to get loaded into it and also vary the columns that are in there. Right now on the SelectionChanged event for the combo box I have something like:
if (defaultComboBox.SelectedIndex == 0)
{
if (extractionDataGrid.Columns.Contains(companyIDColumn))
{
extractionDataGrid.Columns.Remove(companyIDColumn);
extractionDataGrid.Columns.Remove(companyNameColumn);
extractionDataGrid.Columns.Remove(maintenanceColumn);
extractionDataGrid.Columns.Remove(simColumn);
}
extractionDataGrid.Columns.Add(userNameColumn);
extractionDataGrid.Columns.Add(departmentColumn);
extractionDataGrid.Columns.Add(officePhoneColumn);
extractionDataGrid.Columns.Add(officePhontExtColumn);
extractionDataGrid.Columns.Add(otherPhoneColumn);
. [18 columns]
.
.
.
And the opposite for a selected index of 1. There are quite a few columns here and was trying to think of a way to avoid huge blocks of code to initialize the new datagridview columns, adjust the header text, adjust the auto size mode, and various other parameters. Also when I switch back and forth between the selected index, this actually adds the columns in different orders every time. They should be added in the sequence I've set here??
Thanks.
Add all your 0 index columns to a List
Add all your 1 index columns to another List
Pass the list of columns to a new method you create that iterates over the List to add or remove as necessary.
Put a synch lock on your add/remove methods. That is probably what is giving the appearance of different orders due to the
extractionDataGrid.Columns.Remove(companyIDColumn);
i.e. the condition is met before the grid is fully updated.
Alternatively change the conditional so that it is independent of column order and so that it checks a variable that is only set after all the columns have been added and or removed.
i.e.
switch (gridMode){
case GridMode.Company:
this.AddColumns(userColumnList);
gridMode = GridMode.User;
break;
case GridMode.User:
this.AddColumns(userColumnList);
gridMode = GridMode.Company;
break;
}
protected void AddColumns(List<Column> adds){
extractDataGrid.Layout.Suspend();
extractionDataGrid.Columns.Clear();
foreach(Column c in adds){
extractionDataGrid.Columns.Add(c);
}
extractDataGrid.Layout.Resume();
}
Alternatively don't delete columns but rather turn off visibility if that's an option.

How to deleselect / blank a databound ComboBox? SelectedIndex = -1 does not work

I am trying to deselect (blank out) a number of combo-boxes in my windows forms application. In my application I have a Reset method that sets the SelectedIndex for each combo to -1. All of my combo-boxes are databound, i.e. each combo-box is populated using a datasource.
I have noticed that sometimes my Reset method works, i.e. it deselects the currently selected item and blanks the combo. However, other times it chooses the first item (SelectedIndex = 0) straight after I attempt to set it to -1. From a users point of view this looks like a bug as it doesn't always "clear" the form.
According to MSDN:
"To deselect the currently selected item, set the SelectedIndex to -1. You cannot set the SelectedIndex of a ComboBox item to -1 if the item is a data-bound item."
Does anyone know of a work around?
Many thanks
Use combination of the void and property
comboBox.ResetText();
//to reset selected value
comboBox.SelectedIndex = -1;
Don't know if anyone is still interested in this, seeing as it's now 5 years later, but I found a very easy workaround. Totally non-intuitive (I only found it by looking at the reference source code), but trivial to implement:
ComboBox1.FormattingEnabled = True;
Yep, that's all there is to it!
If you're curious, you can peruse the source code to see what's going on. It appears that the root cause of the bug noted by #CuppM is the attempt to set the position in the data source:
if (!FormattingEnabled || SelectedIndex != -1) {
this.DataManager.Position = this.SelectedIndex;
}
I would guess that it should have simply been '&&' instead of '||' in the condition, as the code probably shouldn't be setting the Position to an invalid value regardless of the FormattingEnabled property.
In any case, it allows for a simple workaround. And since the default behavior if the 'Format' property is blank is a no-op, you don't have to change anything else. It just works. :-)
(I should note that I have only tried this with .NET 4.7, so I can't say whether it works for prior versions of the .NET Framework.)
You can try to set the Selected Value or Item to null (Nothing in VB)
I cant remember the behavior of throwing an exception. However, I do remember that I used to insert a value called -1, (None) to the combo-box after it was databounded usually through the databind events. I'd recommend get the data in a List and insert the new value to this list. Bind the combo to the List now.
Only the following code works for me, so try:
comboBox.ResetText(); //framework 4.0
ComboBox1.SelectedItem = null;
For anyone still looking at this old post I wanted to add a note from what Hisham answer.
Make sure to clear your list after inserting his code.
comboBox.ResetText();
//to reset selected value
comboBox.SelectedIndex = -1;
comboBox.Items.Clear();
Try assigning null or String.Empty to the SelectedValue property.
If your target framework is 4.0 - here is the solution:
Install .Net Framework 4.5 (do not change target framework of your project, just install the framework).
After installing, that line deselects databound combobox:
combobox.SelectedValue = 0;
My value member is "Id" int primary key auto-increment, so that field does not contain value 0.
However, that won't work on Windows versions, that do not support .net45
Try to set the [ComboBoxObj].SelectedIndex=-1; which will make it to empty value.
-1 refers to deselect or nullify the value of combobox
Thanks
I have had this problem for a while, but if you use:
'ComboBox.ResetText();'
it will make the text "" and leave the items in the combo box unaffected.
i used the following code in my application
private void UpdateComboBox(ComboBox Box, string Group, List<string> Numbers)
{
Box.Items.Clear();
Box.BeginUpdate();
Box.Items.Add("<<Add Contact>>");
foreach (string item in Numbers)
{
if(item != "")
Box.Items.Add(item);
}
Box.EndUpdate();
Box.ResetText();
}
So i run the method last, once all items are in the combo Box.
Try this line of code:
combobox1.Items.clear();
It works for me.
Add to your combobox one empty item, something like this:
cb.Items.Add("");
After this you can deselect your combobox by selecting the last cb item:
cb.SelectedIndex = cb.Items.Count - 1;
There you go!
You'll have the last place empty in your combobox, but it wont bother you. will it? :-)
I got the following error:
There is no row at position 0
when I was setting ComboBox.SelectedItem to -1.
Replacing by ComboBox.ResetText() worked OK. This was using .Net 4.6.1, with VS 2013 where TextFormatting = True by default for ComboBoxes.
you may try to use this solution..
dataGrid.DataSource = Nothing
dataGrid.DataBind()
hope its help!..:D

C# Datagridview Edit Cell

I'm trying to put the cursor and focus in the last row and a specific cell with the column named 'CheckNumber'. I thought I had it with this:
var c = dataGridView1.RowCount;
DataGridViewCell cell = dataGridView1.Rows[c-1].Cells[0];
dataGridView1.CurrentCell = cell;
dataGridView1.BeginEdit(true);
but it keeps coming up with this error:
Index -1 does not have a value.
Can someone please point me in the right direction!? This is driving me nuts.
Thank you!
Ok, I am going to preface this by saying that I cannot reproduce the issue you are having. However, you mentioned that the error actually occurs at dataGridView1.CurrentCell = cell; which should have ruled out the -1 index error.
Additionally, you said that the error you get is Index -1 does not have a value. That means that even though you have the right index, cell is still coming up as index -1. This means either the cell does not exist, or something else sketchy is happening. Since you sound like you've been at this for a while, I am assuming the cell actually exists.
Since the error doesn't seem to be in any of the 4 lines you've posted I would say take a look somewhere else, like when you first bind the source to the datagridview.
Update: I just found a few links relating to this. Since I don't know how you bound your datagridview, I don't really know if any of these apply, but if any do, let us know! In any case, it seems like it may apply to binding.
From: SO Question 1
If you initially bind an empty
collection that does not inform the
DGV of changes (e.g. a Collection does
not, but a BindingList does), the
initial current row offset will be
correctly set to -1, (Because it is
empty.)
When you subsequently add objects to
your data bound collection they will
still display correctly on the grid,
but the CurrencyManager will not be
informed of any changes, and the
current row offset will remain
stubbornly at -1.
So, when you try to edit a row, the
CurrencyManager thinks you are trying
to edit a row at offset -1, and the
exception is thrown.
To combat this, you need to rebind
before interacting with a row, or
initially bind a Collection etc when
it contains one or more items.
SO Question 2
.NET Monster Question
Check the rowcount first, to make sure that you don't try to access a negative row number when there aren't any rows.
var c = dataGridView1.RowCount;
if(c>0){
DataGridViewCell cell = dataGridView1.Rows[c-1].Cells[0];
dataGridView1.CurrentCell = cell;
dataGridView1.BeginEdit(true);
}

Categories

Resources