Empty data template in Windows 8 Grid app - c#

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

Related

Getting an IEnumerable of all values in a certain column

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.

WPF auto complete box : Selected item Index when searching for repetitive items

I have a WPF auto complete box filled with List which have repetitive items.
Now when an item is selected i need to get the index so that i want to identify uniquely which item is selected. I cannot go by text in auto complete box alone because they are repetitive and so that need to go in conjunction with selected index.
Seems simple enough but i have not been able to find a solution for this. I see there is a
autocompletebox.selecteditem
I have not been able to get anything out of that for scenario mentioned. Please suggest.
There is no index for selected item for auto complete box.
So the solution would be to manage that in your code logic.
This is what i did when i faced an issue where i have to select the first available item when the auto complete box displayed multiple products and user wants to search for a product that is available.
The first scenario would be to display the list of all products and let him search and select a product. So here the user would be entering the product name (which might be repetitive in the auto complete box)
So you have a search on the List of all products. But now when searching you first loop through your list and find if you are searching for a product name that occurs multiple times.
foreach (var products in ListofAllProducts)
{
if (Products.ProductName.ToString() == productname)
{
i=i+1;
tempproducts.Add(products );
}
}
Now you find the first available item by checking the customer name
foreach (var product in ListofAllProducts)
{
if (i == 1)
{
if (Product.ProductName== productname)
{
return product;
}
}
else
{
foreach (var product in ListofAllProducts)
{
if (int.Parse(product .CustomerID)==0)
{
return product ;
}
}
return tempproducts[0];
}
}
return null;
}

Sharepoint calculated field in lookup field

I'm having trouble accessing the value of a calculated field from a list which is in a lookup field on another list in codebehind for SharePoint.
A ListFieldIterator on a page displays a load of options to a user. I need to perform some back-end validation on some particular selections the user has made.
I have a list called "Event Type" from which a user can select Play, performance, display etc. This list has 4 columns - description, enabled, default and filtered. Filtered is a calculated column which is generated based upon the options chosen on the other columns.
The list Events has a column which is a lookup to this list, and which displays the filtered column.
Now on the page this all works great. The options are displayed to the user and they can make their selection. Before adding the calculated field I could access the choice made by doing the below
SPFieldLookup eventTypeField = ListFieldIterator.Item.Fields.GetField("Event_x0020_Type") as SPFieldLookup;
if (eventTypeField.GetFieldValueAsText(ListFieldIterator.Item["Event_x0020_Type"]) == "Performance")
{
// some other logic
errorMessages.Add("There is an error here");
}
Now however when accessing the field in this way I just get an empty string back.
If I attempt to access the chosen item with
string value = eventFields.Item["Event_x0020_Type_x0020_1"].ToString();
Then I get back "8" which is the position in the list of the item I chose. (it changes based on what item in the list I select)
This post Get value of calculate field seems related but I can't see an obvious way to get a calculated field from the lookupfield.
Any suggestions appreciated
It turns out that when using either a lookup column or a lookup column with a calculated field in, as I was, I was going about things the wrong way. This post put me onto the solution. The code is also below.
Essentially I need to access the value stored in the control of the ListFieldIterator and not the value from the item. The code below (from the link above) provides a nice way to do this.
public static List<T> GetControlsOfType<T>(this ControlCollection controls)
{
List<T> resultList = new List<T>();
foreach (Control control in controls)
{
if (control is T)
resultList.Add((T)((object)control));
if (control.Controls.Count > 0)
{
resultList.AddRange(GetControlsOfType<T>(control.Controls));
}
}
return resultList;
}
public object GetFieldValue(ListFieldIterator lfi, string fieldName)
{
FormField formField = lfi.Controls.GetControlsOfType<FormField>().Where(f => f.FieldName == fieldName).FirstOrDefault();
if (formField == null) return null;
return formField.Value;
}

ListView vs. ListBox for multiple column usage

I am currently struggling with the GUI of my application. I have a hard time figuring out whether the ListBox or ListView is more "suitable" for multi-column representation of data.
I prefer "clean" code that is not too confusing to figure out, as spaghetti code and hacking methods can lead to confusion.
How do both ListBox and ListView handle multiple columns?
There's certainly nothing wrong with a DataGridView in this scenario.
Sample:
class Car
{
public string Make { get; set; }
public string Model { get; set; }
public int Year { get; set; }
}
A function to load the data to the DataGridView
private void LoadData()
{
List<Car> cars = new List<Car>()
{
new Car() { Make = "Subaru", Model = "Impreza", Year = 2005 },
new Car() { Make = "Ford", Model = "Mustang", Year = 1984 }
};
dataGridView1.DataSource = cars;
}
Of course, from here things can get more complicated, but if you simply want to display data in a tabular fashion... it's pretty simple.
Check this out
https://stackoverflow.com/a/227355/988830
Though listbox is used for single column and listview is used for mutlicolumn, the answer is it all depends.
Sometimes you may need multicolumn list where you need to add different types of children. You cannot bind them using listview so its better to use listbox in such scenarios. But if you want to sort them by using header, do use listview because it is simple.
In conclusion, I would say if you just have multi column data and nothing more better to use listview else if you want to do fancy stuff like buttons, treeview, expander etc. ListBox is really cool.
Thanks,
Omkar
A DataGridView is nice if you want to be able to edit data straight from the grid, like a spreadsheet. A listview in detail mode is great for simple presentation of lists of data columns. A DataGridView will also be easier to sort, as far as I know.
Generally I do something like this:
private void UpdateListView()
{
mListView.Items.Clear();
foreach (Item item in mItems)
{
ListViewItem listViewItem =
new ListViewItem(item.Value1.ToString()) { Tag = item; }
listViewItem.SubItems.Add(item.Value2.ToString());
listViewItem.SubItems.Add(item.Value3.ToString());
mListView.Items.Add(listViewItem);
}
}
The columns will need to have been defined in the designer, including column header text and column widths.
With the Tag = item; part you will be able to access the selected object with:
if (mListView.SelectedIndices.Count <= 0)
return;
Item selectedItem = mListView.SelectedItems[0].Tag as Item;
if (selectedItem == null)
return;
// do something with selectedItem
ListView is much better for multi-column representation of data. However it seems to get more complicated/ugly code than a simple ListBox.
Still its much better for many reasons, resizeable columns and all that.
I don't think ListBox has multiple columns so you'd have to hack something ugly in.
http://www.xtremedotnettalk.com/showthread.php?t=93443

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