WPF - RadGridView loop through rows. Can't get all rows - c#

I'm trying to iterate through my RadGridView rows, but when I have more than 20 or 30 items, the loop doesn't get all rows.
For example: using this code in a radgridview with 5 items, I can get all of them and do whatever I want, but when my grid has more than 20 items, it gets only 10 rows. Is this a bug or something like that? How can I solve it?
Here's my code:
private List<object> ReturnListFounds(string text)
{
List<object> a = new List<object>();
foreach (var item in myGrid.Items)
{
if (item == null)
continue;
GridViewRow row = myGrid.ItemContainerGenerator.ContainerFromItem(item) as GridViewRow;
if (row == null)
continue;
foreach (GridViewCell cell in row.Cells)
{
if (cell != null && cell.Value != null)
{
string str = cell.Value.ToString();
if (str.Equals(text, StringComparison.InvariantCultureIgnoreCase) || str.ToLower().Contains(text.ToLower()))
{
a.Add(row.Item);
break;
}
}
}
}
return a;
}
#Edit
I found out the problem. The thing is: the method "ItemContainerGenerator.ContainerFromItem(item) as GridViewRow" returns null if the item is outside of the view area. But I'm using this method in a grid containing 123 items and I can only get the row for the 20 first items.
I need to be able to get all of the items, not just the ones in the view area. I have already tried to set the virtualization false (EnableRowVirtualization = false; EnableColumnVirtualization = false;), but it didin't work as well.
Is there a way of getting all of the rows using this method?

Have you tried this?
var rows = StrategyGridView.ChildrenOfType<GridViewRow>();
It works fine for me. Hope it helps!

I tried a lot of things to make this work and I found one. It's not the best way of doing this, but it works. I anyone has anything better, just post here! Share with us!
private List<object> ReturnListFounds(string text)
{
List<object> result = new List<object>();
for (int l = 0; l <= Items.Count; l++)
{
var cell = new GridViewCellInfo(this.Items[l], this.Columns[0], this);
if (cell.Item != null)
{
var props = cell.Item.GetType().GetProperties();
foreach (var p in props)
{
if (p == null || cell.Item == null)
continue;
var t = p.GetValue(cell.Item);
if (t == null)
continue;
var str = t.ToString();
if (str.Equals(text, StringComparison.InvariantCultureIgnoreCase) || str.ToLower().Contains(text))
{
result.Add(cell.Item);
}
}
}
}
result = new List<object>(result.Distinct());
return result;
}

Related

ArgumentOutOfRangeExeption for if statement

Here is a snippet of the code that is causing the error
if(items[0] != null)
{
equippedItem = items[0];
}
Here is a snippet of the items list:
public List<InventoryItem> items = new List<InventoryItem>();
Here is a snippet of the
public InventoryItem equippedItem;
I would change this:
if(items[0] != null)
{
equippedItem = items[0];
}
To this:
if(items.Any() && items[0] != null)
{
equippedItem = items[0];
}
This will check if the list is initialized and has items. If it does have items, you can get the first item from the list.
And if you really want to get the first item from that list at all times, maybe use something like this:
InventoryItem equippedItem = items.FirstOrDefault();
if(equippedItem != null)
{
// Add some cool code
}
The FirstOrDefault gets the first item from a list. If there isn't a first item, the result will be the default value of the type (int = 0, bool = false, InventoryItem = null). You could also use First(), but that would throw an exception if there isn't a first (index 0).
I would try to avoid indexes as much as possible, because it's very sensitive for errors.
I actually found specifically that if you do this it works:
if (items.Count != 0)
{
if(items[0] != null)
{
equippedItem = items[0];
}
}

C# Copy one row from datagrid

I have problem with copying one row from my datagrid and then copy it.
For multiple selected rows it works fine as i want. But for one row not.
This is code for copy row
/// <summary>
/// Method which will copy entire row.
/// </summary>
private void CopyRow(object obj)
{
var datagrid = obj as System.Windows.Controls.DataGrid;
List<string> valsCollection = new List<string>();
foreach (ENotifiedTruck item in datagrid.SelectedItems)
{
valsCollection.Add(item.ToStringLP());
}
var rows = GetDataGridRows(datagrid);
int i1 = 0;
foreach (DataGridRow r in rows)
{
DataGridColumn column = datagrid.Columns[0];
TextBlock cellcontent = column.GetCellContent(r) as TextBlock;
valsCollection[i1] = string.Format("{0}\t{1}", cellcontent.Text, valsCollection[i1]);
i1++;
}
datagrid.ClipboardCopyMode = DataGridClipboardCopyMode.IncludeHeader;
valsCollection.Insert(0, string.Empty);
ApplicationCommands.Copy.Execute(null, datagrid);
string oldresult = (string)Clipboard.GetData(DataFormats.Text);
List<string> rowCollection = new List<string>();
rowCollection = oldresult.Split(new char[] { '\n' }).ToList<string>();
if (rowCollection.Count == 0)
return;
string last = rowCollection[0];
rowCollection = new List<string>();
rowCollection.Add(last);
rowCollection.AddRange(valsCollection);
oldresult = string.Join("\n", rowCollection);
Clipboard.SetText($"{oldresult}");
}
public IEnumerable<DataGridRow> GetDataGridRows(System.Windows.Controls.DataGrid grid)
{
var itemsSource = grid.ItemsSource as IEnumerable;
if (null == itemsSource) yield return null;
foreach (var item in itemsSource)
{
var row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromItem(item);
if (null != row) yield return row;
}
}
Now in this particular line :
valsCollection[i1] = string.Format("{0}\t{1}", cellcontent.Text, valsCollection[i1]);
I got error when i select only one row.
This is the message i get from error: "An unhandled exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll"
Any ideas? Thanks :]
DataGridRow has an Item property that should be the ENotifiedTruck you are trying to use.
You can use that instead of creating a separate collection beforehand.
Also, from what it looks like, you are getting all DataGridRow objects from GetDataGridRows based on the ItemsSource collection, while you are only creating entries in the valsCollection for selected rows.
If you have 1 selected row and 2 or more rows, then I think this should fail with an out of range exception when you get to [1] and valsCollection has no [1].
if(!datagrid.SelectedItems.Contains(r.Item))
continue;
will skip any rows that aren't selected.

Filtering elements of an array

I have an array as
That is, each item has its category in the following index.
I need all the items whose category are TotalNumbers and CurrentNumbers.
I tried
int i = 1;
foreach (string item in statsname)
{
//only number type stats are added to the comboboxes.
if ((statsname[i].ToUpperInvariant()==("TOTALNUMBER")) || ((statsname[i].ToUpperInvariant()==("CURRENTNUMBER"))))
{
comboBox1.Items.Add(statsname[i-1]);
i++;
i++;
}
comboBox1.SelectedIndex = 0;
}
Apparently this does not checks for what I need correctly.
How do I need to modify my codes to get what i need ?
Seems it's better to use a for loop instead of foreach:
for (int i = 1; i < statsname.Length; i += 2)
{
//only number type stats are added to the comboboxes.
if ((statsname[i].ToUpperInvariant()==("TOTALNUMBER")) || ((statsname[i].ToUpperInvariant()==("CURRENTNUMBER"))))
comboBox1.Items.Add(statsname[i-1]);
}
Linq comes to rescue!
var listItems = from s in statsname where s.Equals("TOTALNUMBER", StringComparison.InvariantCultureIgnoreCase) || s.Equals("CURRENTNUMBER", StringComparison.InvariantCultureIgnoreCase) select new ListItem(s);
comboBox1.AddRange(listItems);
Code not tested or compiled, but you can have an idea of what i said.
var filteredValues = Array.FindAll(source, s => s.ToUpperInvariant() == "TOTALNUMBER" ||
s.ToUpperInvariant() == "CURRENTNUMBER").ToList()
I am not sure why you are using index in an foreach loop. The below code should work for you
foreach (string item in statsname)
{
if ( item.ToUpper() == "TOTALNUMBER" || item.ToUpper() == "CURRENTNUMBER")
{
comboBox1.Items.Add(item);
}
}
comboBox1.SelectedIndex = 0;

Collection modified during foreach error

I know you can't modify a collection during a foreach, but I should be able to set variable values of the underlying iterator through it. For some reason the method below, every time it executes is giving be the "Collection was modified..." error:
private static IInstrument AdjustForSimpleInstrument(DateTime valueDate, IInstrument temp)
{
var instr = temp;
foreach (var component in instr.Components)
{
component.Schedule.ScheduleRows.RemoveAll(
sr =>
((sr.Payment != null) && (sr.Payment.PaymentDate != null) &&
(sr.Payment.PaymentDate.AdjustedDate.Date <= valueDate.Date)));
if (
!component.ScheduleInputs.ScheduleType.In(ComponentType.Floating, ComponentType.FloatingLeg,
ComponentType.Cap, ComponentType.Floor)) continue;
foreach (var row in component.Schedule.ScheduleRows)
{
var clearRate = false;
if (row.Payment.CompoundingPeriods != null)
{
if (row.Payment.CompoundingPeriods.Count > 0)
{
foreach (
var period in
row.Payment.CompoundingPeriods.Where(
period => ((FloatingRate)period.Rate).ResetDate.FixingDate > valueDate))
{
period.Rate.IndexRate = null;
clearRate = true;
}
}
}
else if (row.Payment.PaymentRate is FloatingRate)
{
if (((FloatingRate)row.Payment.PaymentRate).ResetDate.FixingDate > valueDate)
clearRate = true;
}
else if (row.Payment.PaymentRate is MultipleResetRate)
{
if (
((MultipleResetRate)row.Payment.PaymentRate).ChildRates.Any(
rate => rate.ResetDate.FixingDate > valueDate))
{
clearRate = true;
}
}
if (clearRate)
{
row.Payment.PaymentRate.IndexRate = null;
}
}
}
return temp;
}
Am I just missing something easy here? The loop that is causing the exception is the second, this one:
foreach (var row in component.Schedule.ScheduleRows)
I suspect this is not .NET-framework stuff, so I assume that row is connected to its collection. Modifying the contents of the row, might shift its place inside its collection, thus modifying the collection, which is not allowed during some foreach-operations.
The solution is simple: create a copy of the collection (by using LINQ).
foreach (var row in component.Schedule.ScheduleRows.ToList())
...

ObjectListView's TreeListView cell editing very very slow

I am using a TreeListView (ObjectListView) http://objectlistview.sourceforge.net/cs/index.html - and populated it with a number of items. One of the columns I made editable on double click for user input. Unfortunately, the editing is extremely slow and going from one cell edit in the Qty column (see picture further below) to the next cell edit takes about 5-10 seconds each time. Also, the cell editor takes a while to appear and disappear. Below is the code I use to populate the TreeListView:
TreeListView.TreeRenderer renderer = this.treeListView.TreeColumnRenderer;
renderer.LinePen = new Pen(Color.Firebrick, 0.5f);
renderer.LinePen.DashStyle = DashStyle.Solid;
renderer.IsShowLines = true;
treeListView.RowFormatter = delegate(OLVListItem olvi)
{
var item = (IListView)olvi.RowObject;
if (item.ItemType == "RM")
olvi.ForeColor = Color.LightSeaGreen;
};
treeListView.CanExpandGetter = delegate(object x)
{
var job = x as IListView;
if (job != null)
{
if (job.ItemType == "PA" || job.ItemType == "JC")
{
var rm = job.ItemPart.GetRawMaterial();
var subParts = job.ItemPart.SubParts.Where(v => v != null).ToList();
if (rm.Count > 0|| subParts.Count > 0)//
return true;
}
}
return false;
};
this.treeListView.ChildrenGetter = delegate(object x)
{
try
{
var job = x as IListView;
if (job != null)
{
if (job.ItemType == "PA" || job.ItemType == "JC")
{
var part = job.ItemPart;
var rm = part.GetRawMaterial();
var subParts = part.SubParts.Where(v => v != null).ToList();
var items = new List<IListView>();
items.AddRange(subParts.GetRange(0, subParts.Count).ToList<IListView>());
items.AddRange(rm.GetRange(0, rm.Count).ToList<IListView>());
return items;
}
}
return null;
}
catch (UnauthorizedAccessException ex)
{
MessageBox.Show(this, ex.Message, "ObjectListViewDemo", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return null;
}
};
var lItems= jobs.ToList<IListView>();
treeListView.SetObjects(lItems );
Expand(lItems[0]);
treeListView.RebuildAll(true);
}
public void Expand(object expItem)
{
treeListView.ToggleExpansion(expItem);
foreach (var item in treeListView.GetChildren(expItem))
{
Expand(item);
}
}
Here is a picture of the cell editing:
Why is the editing so very slow? Am I doing something wrong? What can I do to make it faster?
In your delegates you're using linear searches and several list copies (also linear). And this is for each item.
Bad performance is to be expected.
If you want to improve on this, you can pre-calculate the results instead.

Categories

Resources