Getting an IEnumerable of all values in a certain column - c#

I'm currently working with the Atata framework and using a Kendo grid. What I'm trying to achieve is getting an IEnumerable or a collection containing all the values in a column. The kendo grid is defined as below:
public KendoGrid<TransactionGroupsRow, _> TransactionGroupsGrid { get; private set; }
public class TransactionGroupsRow : KendoGridRow<_>
{
[FindByColumnHeader("Group Name")]
public Link<_> GroupName { get; private set; }
}
I not only want a collection of all the links GroupName, I specifically want the text component of them i.e. what the link would read like on the screen.
So in this example I would want an IEnumerable containing "002999" and "003999".
Let me know if I need to provide additional detail. Thanks in advance!

There are 2 ways to do that.
Use SelectData method. It works quite fast for list of items with count <= 50.
// Just get all items:
IEnumerable<string> groupNames = page.TransactionGroupsGrid.Rows
.SelectData(x => x.GroupName.Content.Value).Value;
// Assert items:
page.TransactionGroupsGrid.Rows
.SelectData(x => x.GroupName.Content.Value).Should.Contain("002999", "003999");
The faster way is using SelectContentsByExtraXPath method. This one will work very fast even for a table with 1000 rows. But you need to specify a relative XPath to the table cell td element inside a row tr element. This can also be extracted to the page object class as a method.
// Just get all items:
IEnumerable<string> groupNames = page.TransactionGroupsGrid.Rows
.SelectContentsByExtraXPath("td[1]", "Group Names").Value;
// Assert items:
page.TransactionGroupsGrid.Rows
.SelectContentsByExtraXPath("td[1]", "Group Names").Should.Contain("002999", "003999");
You can also check Performance Practices for ControlList Atata sample project.

Related

Update DataGridView while running test

I am currently writing a piece of functional test (FCT) software used for testing PCBAs. The main interface between the user has a DataGridView that will be used to display all information pertaining to the functional test. I'm also transitioning from LABView to C# to develop these so I'm still learning a bit.
What I want to do at the start of the application is to show a 5 column x 100 row table for the data. I chose 100 rows to make the table fill up the window (it also looks a little better this way too).
The issue I'm having is when I try to add data to the same row. Note that the first set of data put in the grid will only be in two columns, while data added later on will span all five columns. Here's what I'm trying now to update the datagrid:
mydatagrid.RowCount = 100; //Put
int rowIndex; //variable for tracking where I'm placing data on the table
//Do some stuff that doesn't involve my datagrid
mydatagrid.Rows[rowIndex].Cells[0].Value = someData; //This line executes fine
mydatagrid.Rows[rowIndex].Cells[1].Value = someOtherData; //This throws an exception
//Do more stuff that doesn't involve my datagrid
Another method to update the table I tried was
mydatagrid.Rows.Add(somedata, someotherdata);
While this works nicely, it puts the data at the end of the table, rather than at the top.
Also, later on in the app will also need to something like this:
activaterelays.clicketyclackety();
makemeasurement();
updatedatagrid(); // This function will put data in all five columns
Maybe I am missing something trivial with the setup, at it's my first go at a DataGridView with Windows Forms.
To use indexing in rows and cells in a DatagridView, you must fill it with data first.
Try something like this:
public class MyData {
public string column1{ get; set;}
public string column2{ get; set;}
public string column3{ get; set;}
public string column4{ get; set;}
public string column5{ get; set;}
}
var data = new List<MyData>() {...}// You must insert the 100 items
//Loads the data to DatagridView, after this line you will see the DatagridView populated.
mydatagrid.DataSource = data;
//Now you can manipulate it
mydatagrid.Rows[rowIndex].Cells[0].Value = someData;
mydatagrid.Rows[rowIndex].Cells[1].Value = otherdata;

filter datagridview using another datagridview

I have a text file with size about 10-20 MB.
I want to perfom this options.
1) read the text file and split.
2) move all the data in each line into a datagrid view.
3) create an addition datagridview. that the user can define which line can be visible and which not per a values of 1 column (filter).
I have written a code however however it take a long time.
reading to the first datagrid view the text takes about 40 secound.
when I tried to filter it takes about also 40-50 secound till the user filter it,
is there a way to reduce the time? what is the best way to do this kind of thing? and does using a datasource can be helpful?
Thanks,
I think its better to use linq.
Read your file like this and you have a list of file lines.
var lst = System.IO.File.ReadAllLines(FilePath).ToList();
Now you can filter your list by linq statements.
And you can simply show the list in your datagrid.
If you want to show all data in datagrid, it takes time.
You can also create a class for that purpose
public class MyLine
{
public string Line {get; set; }
public bool IsVisible { get; set; }
}
Then you can read the file and have a list or your class, like this:
var lst = System.IO.File.ReadAllLines("")
.Select(x => new MyLine() { Line = x, IsVisible = true });
Then for getting visible ones write this query:
var Visibles = lst.Where(x => x.IsVisible);
Hope it helps.

Empty data template in Windows 8 Grid app

I'm using the default Grid app template and I had a question that I have not found a good answer to yet.
If you just use the sample data and remove all the data elements from a grouping, is there any way to show an item template that just says "No items" easily?
The group header is still present which is fine, just would be helpful to have an indicator there is no data present in the items list.
I tried a DataTemplateSelector but it isn't used if no items are present. It's a little baffling how something like a ListView or GridView doesn't have an EmptyDataTemplate
Edit
The reason I'm asking about this particular scenario is that this application is showing employees grouped by companies. If you add a new company, I would still like the company's name to show, and if you click on the Header of the group, you could still see information about the company, even if no employees have been assigned.
Therefore my group headings should still be visible to navigate into, even if no employees (items) are assigned. I would like an item directly underneath the group header to say something like "No employees present" but still leave the company information visible.
So for instance
Company 1 >
Employee 1
Employee 2
Employee 3
Company 2 >
No employees present
Clicking Company 2 would still show you information about that company on the GroupDetails page.
I managed to solve my problem with a combination of another question here, and by stubbing in an empty item in my group.
So I stubbed in a false employee with empty data, and then adjusted my DataTemplate. The trick was taking the object's binding container and disabling it for items that matched a specific criteria.
public class CompanyTemplateSelector : DataTemplateSelector
{
protected override Windows.UI.Xaml.DataTemplate SelectTemplateCore(object item, Windows.UI.Xaml.DependencyObject container)
{
var containingItem = container as GridViewItem;
if (item is UserDetails)
{
UserDetails detail = (UserDetails)item;
if (detail.UserId == -1)
{
containingItem.IsEnabled = false;
return Empty;
}
else
{
containingItem.IsEnabled = true;
return DataPresent;
}
}
return DataPresent;
}
public DataTemplate DataPresent
{
get;
set;
}
public DataTemplate Empty
{
get;
set;
}
}
So my result is the following
and then after clicking the header
DataTemplateSelector is your best bet if you want to display a group header and show you have no items in the group. A better option might be to simply not show an empty group - with GroupStyle.HidesIfEmpty

How to sort numbers in a table?

I've got a rather small table containing two columns - one is string and one is supposed to be numbers (I know, everything in a table is just "object").
Is there any way to convert the objects into for example Int or Double to be able to actually sort it in a reasonable way?
The sources for that table are two lists. I could sort the number list, but the data wouldn't match anymore.
Other idea would be to transfer the content of the lists into a multidimensional array and to sort that one but I'd prefer a solution to sort that table directly.
Anyone got an idea?
Rather than working with two lists, merge them:
public class MyRow { // rename me
public int Element { get; set; }
public int Appearances { get; set; }
}
....
var rows = new List<MyRow>();
for(...) {// loop over the two lists...
rows.Add(new MyRow {
Element =..., Appearances = ... });
}
rows.Sort((x,y) => y.Appearances.CompareTo(x.Appearances));
Then either just loop and create cells, or (easier) just set rows as the data-source for the table and let it bind itself.

WPF: SelectedItems with duplicate object references

So lets say I have these classes:
public class Person
{
public string Name { get; set; }
}
public class PersonCollection : ObservableCollection<Person> { }
And lets say I have a ListView whose ItemsSource is bound to a PersonCollection. Now lets say I have this code:
public void AddPeople()
{
Person p = new Person() { Name = "Someone" };
MyPersonCollection.Add(p);
MyPersonCollection.Add(p);
MyPersonCollection.Add(p);
}
So now I have a ListView with three items in which all three items are references to the SAME object. So now I select lets say items with index 0 and 2 in the ListView.
The ListView.SelectedItems property will say I have ONE item selected since both visually selected items are the SAME object.
So how can I get the visually selected items so I can remove the items at indices 0 and 2, without removing the item at index 1?
In WinForms there is the ListBox.SelectedIndices property that would be useful here, but we don't have that in WPF, unfortunately...
You could iterate through the ListViewItems using ItemContainerGenerator.ContainerFromIndex, check ListViewItem.IsSelected and then remove them by index. However, this doesn't play well with virtualization because ContainerFromIndex could return null if you scroll away from the item and it gets virtualized.
The code would look something like this:
for(int ixPerson = myListView.Items.Count - 1; ixPerson >= 0; ixPerson--)
{
ListViewItem personItem = myListView.ItemContainerGenerator.ContainerFromIndex(ixPerson);
if (personItem.IsSelected)
{
mySourcePersonCollection.RemoveAt(ixPerson);
}
}
There are cases where this makes sense, adding people to a queue where appearing more than once is desirable for instance. For this case it seems like WPF is designed poorly. Is it possible to manually iterate between all items in the collection and check their selection state?
I think there's something wrong with your model! Whatever it is you are trying to achieve, I would try and find a more robust way of doing it.

Categories

Resources