Binding a structure containing a hashtable to a grid - c#

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.

Related

WPF datagrid multiple property grouping

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?

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.

How to create the ability to apply a generic data source class

This is maybe something I know how to do or have already done it in the past. For some reason I am drawing a blank on how to wrap my head around it. This is more for learning as well as trying to implement something in my app.
I am using a set of third party controls. These controls offer a lot of functionality which is great. However, I want to be able to create a custom object that handle the logic/properties for the datasource of this control.
For example, there is a spreadsheet like object that I am using. You supply the spreadsheet like object some data and it pulls in your data. The problem here is that you need to set the columns, their data types, and other formatting/events as well as some logic to spit the data back to the user.
List<CustomClassWithProperties> dataSource
The custom class has some properties that will be translated to the columns. Like ProductName, Price, SalesDepartment, DatePurchased etc. This can be done by supplying the spreadsheet the columns and their data types each time. I want to be able to create a helper class that you just supply a list, a visible column list, and an editable column list and the data will fill in without any other issues.
Using the above list, I would imagine something similar to this:
DataHelperClass dtHlpr = new DataHelperClass(List<CustomClassWithProperties> data, List<string> visibleColumns, List<string> editableColumns)
This data helper class will take the data input list as the spreadsheet data source. It would then take the visibleColumns list and use that to set the visible rows, same for editableColumns.
Where I am running into a mental block (long week) is when I want to be able to reuse this. Let's say I have a List that has completely different properties. I would want my constructor for the data helper to be able to handle any List I send to it. Looking at whatever code I can get to for the third party controls, it appears that their data source is of type object.
Could someone point me in the right direction? I am thinking it has to do with generics and some interface implementation. I just honestly cannot think of where to start.
You can make the class itself generic:
public class DataHelperClass<T>
{
public DataHelperClass(List<T> data, ...) { ... }
}
DataHelperClass<CustomClassWithProperties> dtHlpr = new DataHelperClass<CustomClassWithProperties>(List<CustomClassWithProperties> data, List<string> visibleColumns, List<string> editableColumns)
You'd then perform your reflection against typeof(T).
I'd also be tempted to use IEnumerable<T> rather than List<T> if possible, but that's a matter of preference, more or less.
This is similar to using a simple List<object>, except that it enforces that all objects in the list inherit from the same type (which might well be object), so you get some more type-checking than you otherwise would.
You mentioned interfaces, I don't see any reason here to include that (from what you've told us, at least), but you can certainly make a generic interface via the same syntax.

C# Generic Table from DataContext

I'm attempting to create a generic WPF form or page, that when called, will load in data from a LINQ table. Here is the concept:
I have three tables in a LINQ DataContext that are identical (apart from the data within)
TypeID and Type are the columns
I would like to generically pass that data in those tables into my second form depending on which table the user selects (essentially so they can narrow down the list of objects of said Type.
I've seen some responses, (in particular the accepted answer to this one LINQ query with a generic table) that are very close to what I am looking for, but not quite. One issue I have with the above answer is that T must be a reference type.
I've done more searching and found some more answers like:
someClass<T> : <T> where T
But unfortunately these are further from my own context and I am unable to bridge the two concepts of what is happening. Below I have posted what I hope to do.
someDataContext db = new someDataContext();
private void pageLoader<T>(){
newPage n = new newPage(T) //This is where I was hoping I could pass the table(s) to the constructor.
}
And here is the constructor:
newPage(T){
listBox l = new listBox();
l.datasource = T;
}
Any assistance in any direction would be helpful (besides MSDN, please. I've been there and I'm still lost.)
Let start from the top. LINQ is merely an abbreviation for Language Integrated Query. It is interchangeable with Lambda. Different syntax but both accomplish the same task. Querying a collection or datasource. See http://msdn.microsoft.com/en-ca/library/bb397926.aspx
You are referring to the EntityFramework Code First approach of creating a database. LINQ is merely a way to access and manipulate the information within.
With that out of the way, what you are pointing out is a Generic Method and a Generic Class. T is simply a standard naming convention for a generic type. You could use any representation you like. If you are going to be passing in entities, you might use TEntity for example.
See http://www.dotnetperls.com/generic-method
http://www.dotnetperls.com/generic
When you see someClass where T, this is a constraint for type parameters.
And finally, what you have been waiting for...
https://codereview.stackexchange.com/questions/19037/entity-framework-generic-repository-pattern
The following should put you on the right path.
http://blog.gauffin.org/2013/01/repository-pattern-done-right/ <- This would be more of a better starting tutorial

Using ASP.NET Repeaters with Object Properties

I'm trying to use ASP.NET's Repeater objects to loop over properties of an object.
For example... I have an ObjectDataSource to grab object "Program" by ID...
Program has properties such as Program.Stakeholders and Program.Outcomes which are Lists of "Stakeholder" and "Outcome" objects.
Now... what I'd really like to do is use the Repeaters to target these Properties and loop over the lists they contain. However, as far as I know I'd have to set up a separate data source for each one, tied to an individual method to retrieve each list.
Can anyone provide a better way to use these Repeater objects, or point me at some resources which would help? If this doesn't make sense I can try to clarify it more.
Using the built-in ObjectDataSource mapping up a separate datasource for each item is probably the only straightforward way (and the only way that's easy enough to be worth the effort...).
Is it a requirement that you use the ObjectDataSource, or can you choose a different way to get the data from the storage? I would recommend either using Entity Framework (which imho rocks) or creating your own custom types to which you get the data with a custom designed DAL (which is a lot more work than using EF, but if you're, like some, concerned that EF is still in infancy this might be your option).
In either case, you'll end up with a C# class called Program, which has properties of type IEnumerable<Stakeholder> and IEnumerable<Outcome> called Stakeholders and Outcomes respectively. You can then use these as datasources for the item repeaters and set them in the ItemDataBound event of the ProgramRepeater, maybe something like this:
protected void ProgramRepeater_ItemDataBound(object sender, ItemDataBoundEvent e) {
Program dataItem = (Program)e.DataItem;
Repeater stakeholderRptr = (Repeater)e.Item.FindControl("ProgramRepeater");
Repeater outecomeRptr = (Repeater)e.Item.FindControl("OutcomeRepeater");
stakeholderRptr.DataSource = dataItem.Stakeholders;
stakeholderRptr.DataBind();
outecomeRptr.DataSource = dataItem.Outcomes;
outecomeRptr.DataBind();
}
This is assuming that you're using ASP.Net WebForms, of course. In ASP.Net MVC it is even easier - you just send the Program object to the View as the Model object, and loop through its Stakeholders and Outcomes in a couple of nested for loops directly on the View.
Note: All code is provided as is, and I do not guarantee that it will run as expected or even compile. It is just to give you an idea of what to make your code do - not necessarily the exact code you need to solve your problem.

Categories

Resources