I need your opinion about UI and Databinding in WPF.
I had argue with my supervisor about UI & databinding. There is A class, it has ObservableCollection of B class, and B class also has ObservableCollection of C class. These classes are used while communicating with NI CAN and LIN device(it is not case).
On the other hand, in user interface there are bunches of TreeView and DataGrids. There are several instances of A class which is used to store data from devices and files, and they are binded to Treeview and Datagrids. But, he disagrees with this, and says to make separate other list of variables for TreeView and Datagrid to data binding. As he says UI data and other must be separate and I agree with it. But, in this case there are several lists of lists of lists and for example: copy from one list to other list when there is change on data takes much time and calculation ( -> UI element ). And other problems also.
I need your your opinion or other advice to come out better solution.
Thank you!!
It sounds like you are a student and doing this work as part of your studies. Either way, there is something to learn here.
Why not implement both approaches and see how they differ, and which you prefer? As it stands your question does not provide enough information for anyone else to tell you, and there is no way to short cut this kind of learning in my experience.
Related
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.
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.
I'm fairly new to WP7 and totally new to Expression Blend.
I have a ListBox bound to a List of custom objects,
List<Person>
Each item in the list contains a custom control, MyControl which is bound to Person.
MyControl contains a TextBox which is bound to the Username property of Person.
All of this works fine. My question is: how do I set a default value for the TextBlock so that it becomes visible in the Designer or ExpressionBlend? With it being data bound, it has no text till it runs ... so I can't actually do any fancy styling using these wonderful tools unless I repeatedly delete the binding code to replace it with a string, make the changes, replace the binding code, repeat. Seems long winded!
Thanks,
Steven
What you want is "Design time data".
There are a number of ways of doing this. Fortunately there are also lots of resources online which explain it.
#Steven Have you looked at creating sample data in Blend to do what you require and then some binding to actually attached the data to the control bound to your list? You might like to check out Blend Sample Data as it guides you through a simple example of doing just that. You might then be able to adapt to to your own ends.
It depends if you are using any MVVM model or not.
My suggestion, if you are not using a MVVM, is to use Blend Sample data, is fast and quick.
If you are MVVM Light I've found very usefull to create two files:
DataService.cs - contains the real connection and data
DesignDataService.cs - contains the sample data
The two libraries are identical, from an call perspective so that in the ViewModelLocator you can swap them:
if (ViewModelBase.IsInDesignModeStatic)
{
SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
}
else
{
//SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
SimpleIoc.Default.Register<IDataService, DataService>();
}
In the Design class I've decided to create an XML file for each Model so that it's easy to change the sample data and test all possible scenarios.
I then use the Deserialize function to read it:
csNodeList _Copyrights = new csNodeList();
resource = System.Windows.Application.GetResourceStream(new Uri(#"Design/sampledata.xml", UriKind.Relative));
streamReader = new StreamReader(resource.Stream);
serializer = new XmlSerializer(typeof(csNodeList));
_Copyrights = (csNodeList)serializer.Deserialize(streamReader);
Please note that the file sampledata.xml has to be stored in folder Design and must be defined as Content not as Resource.
It is suggested to improve performance and load time.
M
I'm using the datacontextproxy class defined by Dan Wahlin to solve what seemed so very difficult for the many many hours leading up to that discovery.
I have a combobox that is bound to an ObservableCollection<Accounts>. The combobox also has the values: DisplayMemberPath=AccountNumber, and the SelectedValue={Binding SelectedAccount}. I then have a DataForm that has its CurrentItem property also bound to SelectedAccount. Inside my DataForm, I have a handful of fields that require additional dropdowns (AcctCode, UsageCode, etc). To mitigate the binding issues I ran into inside of a DataForm, I implemented the datacontextproxy, allowing me to set the ItemsSource of my cbobox to {Binding Source={StaticResource DataContextProxy}, Path=DataSource.AccountCodes}". This is working great in terms of the end result.
Before stumbling onto this, I really struggled with this find. I'm not using a domaincontext, so I couldn't use Kyle Mcllelans ComboBoxex, nor could I use the vast majority of solutions offered. I did try to create an instance of my ViewModel as a local resource in my View, but a) I felt dirty in terms of MVVM, and b) It failed to create a new VM instance, as my VM requires a number of service references to be passed in on construct.
In any case, I'm simply wondering if there's a way I should be doing this that's either more performant, more MVVM, more maintainable, more bestest'er, etc etc.
Thanks,
Scott
Scott I also have settled on using the DataContextProxy. I think use of it still provides a good MVVM solution where the view only has knowledge of the VM via binding or commanding.
I see use of it as a temporary solution until Silverlight 5 ships. In Silverlight 5 ancestor binding is introduced which will provide more flexibility in data binding.
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.