WPF datagrid multiple property grouping - c#

I have a wpf datagrid displaying complex data. I need to be able to group the data by 3 properties simultaneously without any nesting.
Simplified example:
Id, Name, Town Visited, Date of Visit, Shop visited
I need to be able to visualise each visit and easily see how many shops were visited in that instance. To do this, I'll need to group on id,town visited and date of visit together.
Currently I have the following:
BindingListCollectionView tableData = CollectionViewSource.GetDefaultView(*datatable from sql*) as BindingListCollectionView;
tableData.GroupDescriptions.Add(new PropertyGroupDescription("Id"));
The data comes in directly from a SQL datatable and is only grouped on the Id property.
I have done extensive research on how to do the multiple grouping and the most common answers have been to place an additional property on the data object - which would require me making a new viewmodel object for every table I take from SQL (there are many) and placing a new property on each.
Or creating a converter to take the datatable object and produce a group property.
I have not found a particularly helpful guide on the second option and would really rather not have to create several new view models if I don't have to.
Is there any better way to do this grouping? Can anybody explain to me how to create a converter for this if that's the best way?

Related

Dynamically create a class and then create a list<dynamicClass> based on it in C#

I want to create a class and its properties on run time, the properties will be like Year2001, Year2002, Year2003, Year2004, Year2005... I get these property names on run-time, I get them in a list. Later I need to use this class to create a list which I need to show in the kendo grid.I surfed a lot and thought of using ExpandoObject, but was unsuccessful.
If all properties will be of the form YearX and contain some information about or related to that year, then I would strongly recommend you (if at all possible) to go with something along the lines of an IList<YearInfo> where YearInfo is some object containing the info you need for every year, including an integer property indicating what year the object corresponds to. If you require these objects to be unique you could use an IDictionary<int, YearObject> or ISet<YearObject> instead.
Reflection can be powerful, but it it comes at the price of complexity and loss of type safety/compile-time checks. Avoid when possible.
Sounds to me like you are really wanting to a grid with grouping support. Your idea of having the system create a CLASS at runtime is not going to fly. Even if it were possible, which I doubt it is, it is absolutely the wrong approach.
Like I say - have a read about Grouping / Hierarchy on Grid Controls (Kendo grid example here), and maybe have a look at OLAP cubes as well...
Although you have had some answers I would also like to suggest an alternative way of doing this which is using DataTables. This is the approach I take when I have any "Dynamic" data sets that I want to present to the grid.
This is also the approach that Telerik themselves take with one of their code samples.
here are a couple of links to show them doing this to DataTables and Dynamic Objects
Grid Binding to Data Table
Grid Binding to Dynamic Objects
Personally I find the binding to Tables easier to deal with as I am used to dealing with Data Tables.

Which one is a generally better concept: store selected item or only its key (aka id)?

I have a quite big dilemma nowadays about general viewmodel design concepts. I mean general, like it's not exactly bound to a given language or environment: I had same dilemma when I wrote viewmodels for Winforms, WPF or KnockoutJS.
As a simplified use case, consider that I have a view where I have to select a country and a city from two select boxes. Both are represented in the database with a unique ID, a Name, and some other relevant information like - let's say - Population. Now imagine that I have to present a textual form of the currently selected data in for example the view's heading like "You've selected London, England". Now here is my two alternatives for creating a viewmodel, I will try to enumerate the pros/contras which I'm already thinking of below each version. The code is written in kind of pseudo way to be as generic as possible.
class RegionModel {
ID: number;
Name: string;
Population: number;
}
Version 1: Storing the selected object.
class MainView {
SelectedCountry: RegionModel;
SelectedCity: RegionModel;
SelectionInfo: string; // computed, should return the "You've selected ...." caption
Countries: List<RegionModel>; // datasource for country select
Cities: List<RegionModel> // datasource for city select
}
Pros:
Straightforward and easy to understand due to that the selected
item's type is the same as the selectable items' type.
Easy to compute such infos like "You've selected ..." because all the
members of the currently selected item are present directly.
Cons:
It holds more information than usually a consumer API needs. Usually
it needs only the ID.
If it's used in a client-side app, the whole selected object will be
returned to the server, consuming bandwidth.
If the consumer API needs only ID's (like in most cases), I have to
solve some kind of conversion before I pass it. In a web app probably
during serialization to JSON for example.
Version 2: Storing only the ID's of the selected items
class MainView {
SelectedCountryID: number;
SelectedCityID: number;
SelectionInfo: string; // computed, should return the "You've selected ...." caption
Countries: List<RegionModel>; // datasource for country select
Cities: List<RegionModel> // datasource for city select
}
Pros:
It's efficient in the way that it contains only the information which
is most likely needed by consumer APIs.
No additional conversion is needed, and efficiently can be passed
nearly "as is" to a server-side or other API.
Cons:
Not so straightforward and readable (in my opinion).
What about computing the info string? That's now much harder, I need
to grab the needed members from the selection source lists with a
search by the given ID, so it depends heavily on the consistency of
those lists (I mean the item must be present there).
I hope it won't be closed quickly as unconstructive. Any kind of advices, thoughts or experiences will be appreciated. Also, if the answer is "it depends", please try to give my some points where and when to use which.
UPDATE
I think my question was a bit unclear. I know about decoupling viewmodel from database entities, here I never mentioned database entities. I mentioned an "abstract consumer API". In a concrete scenario: if the API needs the selected items' Names, and my API needs only the IDs, which alternative should I choose, and where should do the conversion?
For example my server expects a data format like this (JSON):
{
"SelectedCountryID": 2,
"SelectedCityID": 5
}
and nothing else. How could I handle it in an elegant way? I would like to avoid repeating myself by doing a manual conversion.
Depending on how your datasources are implemented, it may make not difference: if you are retrieving the list of countries and cities, you can either store a reference to the selected value, to one of its fields or its index in the list.
Disregarding that, you should decouple your view model entities from your database entities and put into your view model ones only those fields required by the views. This way, your information traffic is minimized and your code is less affected by changes in the database.
EDIT following OP's update:
Talking about interacting with an API instead of a database, I think you can apply the same ideas, just replacing "database entities" by "service layer entities" (for instance, the JSON coming in/out your server). Take the returned data that into your view model objects, holding those attributes that you need. Obviously you also may need to store an id as you stated, when you'll need to refer to the same entity later on.
From a theoretical point of view, you should not include any other fields not consumed by the view, but you could do so depending on your requirements. For instance, in cases when you'll need to pass those fields back to the service layer and you don't want to query again by id to retrieve the service entity. However there are other alternatives to this (for example, some kind of cache), the exact balance depends on your requirements.
Base on MVVM pattern your viewModel should be an object with all properties which you need to display in view. ViewModel should be only used to be strictly binded to the view. Anyway your example it's not very good in my opinion. You shouldn't think about viewModel in case of storing something, please think more about presenting data.
Please remember that before you have data in database you have to insert it. So if you have some form with First Name and Last Name, user at first must fill this form and data must be insert into database, without it you don't have any ID.
To summarize in my opinion viewModel should have properties which you have to present to the end-user.

Dynamic column datagrid in wpf

I have a case where in the columns of Datagrid are not fixed . i.e it has to be generated depending on some conditions.
How can i store the values in the DB and display the datagrid with them using MVVM pattern.
P.S : I have a main grid and a sub grid and depending on the value he chooses in the main grid i need to form the below grid. My concern also in storing it in the DB, since there can be 5 columns or sometimes 20.
Any similar links or references will also be useful.
This can be totally done in an MVVM compliant way, but isn't necessarily trivial for a beginner, and isn't appropriate for simple applications.
One approach I like to use is to keep a collection of column descriptors serialised in the database1. The column descriptors are simply my own custom DTO data classes and contain properties related to a column, i.e. width, column type, whether it is visible, whether it's visibility can be toggled, it's ordinal, etc. This is all done using simple structs and or primitive .Net types, but specifically doesn't have any UI related data types in it at all2.
This list of ColumnDescriptors can then be serialiased to and from XML, and stored in the database either in an nvarchar or XML column. Especially on SQL Server an XML column is better as you can natively query deep into the XML structures stored in the database column.
As it is a UI layout thing, it is up to the view to query the right set of column descriptors from the database, I then pump that collection through a static GridColumnFactory class which iterates the descriptor objects and creates me the appropriate grid columns and assigns the appropriate values to them. Once the factory returns that collection the view can then add them to the DataGrid's columns collection.
The benefits of this approach:
If I swap out the DataGrid that is used (i.e. swap from one vendor to another, say DevExpress to ComponentOne or native WPF), I can simply change the types of columns returned from the factory class
If I swap anything in the UI then I don't need to touch the column descriptors that are stored.
Serialising to and from XML means that if I do add/remove properties from the descriptors then older stored copies can still be accommodated, they aren't instantly broken the moment I release an update
One of the best features of all is that I can change the stored column layouts with a simple SQL statement, I don't have to also release compiled code
One last thing - using column descriptors makes it trivial to implement a user specified layout, i.e. when you let them drag columns around and then want to save the layout for next time
If I want to get really funky, the column descriptors can be returned from a webservice
1 For a website these could also be stored in a loose XML file which is then read in and kept in cache.
2 For this approach you should always avoid using specialised or vendor specific data types, as they don't necessarily serialise well (if at all), and will become a weak point in the future - these will be the most likely things you have to change, and if these change you break any stored descriptors you've already got.

Binding a structure containing a hashtable to a grid

I'm trying to create a pivot of a translation table. Basically the table is like that :
SystemText(Category, Name, LanguageCode, Text)
I have created a model object which has these fields as properties and I'm using NHibernate to get the data from the database.
Now what I want to display is a grid to edit the translations that will display on the same line the category, the name of the text and all the available languages (languages that are not fixed in advance). For example :
Category | Name | English | French | German
I've managed to create a Linq query to create the pivot that I will need to do that. It looks like that
Dim test = From systemText In _systemTexts _
Group systemText By Key = New With {Key systemText.TextCategory, Key systemText.TextName} Into g = Group _
Select New With {Key .TextCategory = Key.TextCategory, _
Key .TextName = Key.TextName, _
.Languages = g.ToDictionary(Function(st) st.LanguageCode, Function(st) st.Description)}
Now the only trouble I have is to bind the objects to my gridlist. I would create the columns of the grid dynamically when the form is loading, depending on the languages available. I thought that using something like Languages("EN") in the DataMember property would work, but it doesn't seem so.
I'm a bit blocked now, I thought about using something else to replace the Dictionary for the languages but I don't really see what I can use.
So, after some trial and error I ended finding some ways to do that.
The first, and one of the most complex ways of doing it I have found was was given by Vladimir Burodov on this blog post. The idea basically is to dynamically create an anonymous type that has a property for each key in the Dictionary. It's very clever and very useful, but a bit overkill for the little task I needed.
Another way around was using Custom Property Descriptors. The idea is to create a custom list type that will, when asked for the special property call a custom function that will send back the value. Examples of this method can be seen here. Again unfortunately I couldn't use this method because the grid component I am using cannot use the custom property descriptors.
I also thought about using Dynamic Linq to generate dynamic queries where I would have been able to change the property names of the query result (see this Scottgu's article) but I didn't want to use another library just for the simple thing I needed.
Finally what I endend doing was dynamically creating a DataTable, inserting the result of the Linq query in it, binding the DataTable to the grid and finally listening to the RowUpdated event and do the CRUD operations to the NHibernate collections. It works quite nicely and the code is easy to understand.

C# Factory Pattern

I am building a search application that has indexed several different data sources. When a query is performed against the search engine index, each search result specifies which data source it came from. I have built a factory pattern that I used to display a different template for each type of search result, but I've realized that this pattern will become more difficult to manage as more and more data sources are indexed by the search engine (i.e new code template has to be created for each new data source).
I created the following structure for my factory based off of an article by Granville Barnett over at DotNetSlackers.com
factory pattern http://img11.imageshack.us/img11/8382/factoryi.jpg
In order to make this search application easier to maintain, my thought was to create a set of database tables that can be used to define individual template types that my factory pattern could reference in order to determine which template to construct. I figured that I'd need to have a look up table that would be used to specify the type of template to build based off of the search result data source. I'd then need to have a table(s) to specify which fields to display for that template type. I'd also need a table (or additional columns within the template table) that would be use to define how to render that field (i.e. Hyperlink, Label, CssClass, etc).
Does anyone have any examples of a pattern like this? Please let me know.
Thanks,
-Robert
I would offer that this proposed solution is no less maintainable than simply associating a data source to the code template, as you currently have now. In fact, I would even go so far as to say you're going to lose flexibility by pushing the template schema and rendering information to a database, which will make your application harder to maintain.
For example, let's suppose you have these data sources with attributes (if I'm understanding this correctly):
Document { Author, DateModified }
Picture { Size, Caption, Image }
Song { Artist, Length, AlbumCover }
You then may have one of each of these data sources in your search results. Each element is rendered differently (Picture may be rendered with a preview image anchored to the left, or Song could display the album cover, etc.)
Let's just look at the rendering under your proposed design. You're going to query the database for the renderings and then adjust some HTML you are emitting, say because you want a green background for Documents and a blue one for Pictures. For the sake of argument, let's say you realize that you really need three background colors for Songs, two for Pictures, and one for Documents. Now, you're looking at a database schema change, which is promoted and pushed out, in addition to changing the parameterized template you're applying the rendering values to.
Let's say further you decide that the Document result needs a drop-down control, the Picture needs a few buttons, and Songs need a sound player control. Now, each template per data source changes drastically, so you're right back where you started, except now you have a database layer thrown in.
This is how the design breaks, because you've now lost the flexibility to define different templates per data source. The other thing you lose is having your templates versioned in source control.
I would look at how you can re-use common elements/controls in your emitted views, but keep the mapping in the factory between the template and the data source, and keep the templates as separate files per data source. Look at maintaining the rendering via CSS or similar configuration settings. For making it easier to maintain, considering exporting the mappings out as a simple XML file. To deploy a new data source, you simply add a mapping, create the appropriate template and CSS file, and drop them in to expected locations.
Response to comments below:
I meant a simple switch statement should suffice:
switch (resultType)
{
case (ResultType.Song):
factory = new SongResultFactory();
template = factory.BuildResult();
break;
// ...
Where you have the logic to output a given template. If you want something more compact than a long switch statement, you can create the mappings in a dictionary, like this:
IDictionary<ResultType, ResultFactory> TemplateMap;
mapping = new Dictionary<ResultType, ResultFactory>();
mapping.Add(ResultType.Song, new SongResultFactory());
// ... for all mappings.
Then, instead of a switch statement, you can do this one-liner:
template = TemplateMap[resultType].CreateTemplate();
My main argument was that at some point you still have to maintain the mappings - either in the database, a big switch statement, or this IDictionary instance that needs to be initialized.
You can take it further and store the mappings in a simple XML file that's read in:
<TemplateMap>
<Mapping ResultType="Song" ResultFactoryType="SongResultFactory" />
<!-- ... -->
</TemplateMap>
And use reflection et. al. to populate the IDictionary. You're still maintaining the mappings, but now in an XML file, which might be easier to deploy.

Categories

Resources