So here is the current problem I'm facing:
I have C# Business Object classes that are generated dynamically from XML Schema.
I build forms dynamically to display and capture data bound to my Business Objects.
I store my serialized (xml) objects into the database.
I need to persist the display properties associated to each Property in my Business
Object C# classes (How to accomplish this??)
Lets say I have a Person Business Object:
public class Person
{
public string Name {get;set;}
public PhoneType Phone {get;set;}
}
public class PhoneType
{
public string HomePhone{get;set;}
public string WorkPhone{get;set;}
}
Now let's say I create a new Person:
Person me = new Person();
me.Name = "BOB";
me.Phone = new PhoneType()
me.Phone.HomePhone = "1234";
me.Phone.WorkPhone = "4321";
Now when I build my form I know that Person.Name is a TextBox of Width = 300 and Height = 30
and my PhoneType.HomePhone and PhoneType.WorkPhone are TextBoxes of Width 200 and Height = 30.
What are the best ways to persist those Display Properties in the DataBase and associate them to each of the Properties in my Business Objects? Considering that most of my Business Objects are represented by very deep object graphs... so I'm wondering what the best way is to recursively store and regenerate display properties from Database based on the deep hierarchical nature of my model.
Now a few conditions:
-I don't want to store static forms since my application is very dynamic. XSD -> Code -> Form
-Display properties may be user-specific (e.g. backcolor of certain field), so can't just have generic form templates
-I just need a good mechanism to associate POCO properties to display properties so I can build my forms on the fly and persist changes to the database
I'm currently exploring the possibility of creating a PropertyBag (collection) property in each of my Business Objects and populate them recursively as I navigate the object graph, but haven't gone far yet..
The way that we handle this is to provide unique identifier attributes to each of the classes, then store the UI definition, including required fields, size, label values, etc, in the database.
We actually also attribute each of the properties in the classes in order to separate those that are visually important from those that are "helpers" only.
At run time, we use reflection to retrieve the attributes for the classes and properties that are to be displayed, then fetch the appropriate list of visual modifiers from the database.
Related
My Model classes (Entity) are all generated in one project. Is it possible for a property getter in that model to return class/object thats not available in that project but in a later one that uses that model.
Person
Int Id
String Name
Object ImageInfo
Different Project Class that's not available to Model project/namespace
Imagecls
WebClient myWebClient
byte[] ImageByteArray
When I get the multiple records of the Person entity, I don't have security and other info needed for ImageCls in that project. I want to access those records in a project higher up in the solution, but dont want to have to iterate through the set of Person records and add the class/object or create a new object that has both.
So want a Property that will do the Get at time of usage for displaying on screen so was thinking delegate would do this.
Object ImageInfo
Get
{ return somedelegatemethod() }
Where I could change out the somedelegatemethod in the other project. How do I do this or is there a better way?
I am struggling to implement MVVM pattern in my current project.
"ClassA" continuously gets required data from a remote device and stores this data inside it's fields. It is a model, I guess. ClassA updates required information via Update method.
"ClassB" continuously gets the data from "ClassA" and stores it in corresponding properties. Looks like it is a view model.
View is a simple MainWindow.xaml with a DataGrid inside.
I have the following questions:
1) How do I update ViewModel?
Should ClassB have an Update method, which accepts an instance of ClassA and updates corresponding fields?
2) Where do I store an instance of ClassA?
Should ClassA be a field of ClassB? If it should, then how do I update Model?
I thought of something like the following:
public void UpdateB()
{
ClassA.UpdateA();
this.FieldOne = ClassA.FieldOne;
this.FieldTwo = ClassA.FieldTwo;
}
4) Does model have it's update method at all or model just stores the data?
3) What do I do inside MainWindow.cs, aside from windows initialization? Do I update view model (ClassB) there?
I find it best to have a object representing an item in each layer of abstraction. This includes the form of the data as it exists on the disk. Remember that in MVVM, the only real goal is to promote loose coupling between the interface(User Interface) and the implementation(ViewModel functionality).
For example, if I have objects stored in XML files, I will have an object in my data access layer that exists only for the proper management of the XML data. Let's call it ObjectXml. This object only contains data in the form that is native to the data on the disk. In this case, all data has a string representation, as in the XML files.
In the model layer, you will have the data representation of the XML file in the expected data types. Let's call this Object. The property getters and setters may access and set the string representation of the data by performing conversions in both directions. This way, the data is ready to be persisted to the data source(xml file, database etc.).
In ObjectViewModel, properties may access those in Object. The viewmodel contains all the members for representing and modifying the model.
Note that ObjectXml is really only beneficial when you are only allowed to store string information, or when a suitable schema does not exist for your data types.
At the end, you have a hierarchy of containment such as the one below:
public class ObjectXml
{
[XmlArray("People"), XmlArrayItem("Person")]
public List<PersonXml> People { get; set; }
//PersonXml is an xml data model similar to this one
[XmlElement("Item")]
public string Items { get; set; }
}
Here is the model for the Xml object:
public class Object
{
private ObjectXml _xmlContext;
public Object(ObjectXml xmlContext)
{
this._xmlContext = xmlContext;
}
public List<Person> People
{
get
{
//Person requires a constructor that takes a PersonXml object in order for this to work properly
return this._xmlContext.People.Select(x => new Person(x)).ToList();
}
set
{
this._xmlContext.People = value.Select(x => new PersonXml(x)).ToList();
}
}
public double Item
{
get { return double.Parse(this._xmlContext.Item); }
set { this._xmlContext.Item = value.ToString(); }
}
}
Obviously, it's not wise to name your class Object as it's a reserved word in C#. Hopefully I've given you some ideas of how to access and update data in a robust and extensible manner.
In short, you don't need an update method at all. Also, short of constants and property backing fields, there are very few reasons to need direct field access in C# MVVM.
See below. Do not listen to people that say the ViewModel and Model need to be decoupled. The main purpose of the model is an intermediary layer that prepares data to be saved or loaded into the program and to store data in a way that is agnostic to both the data and the program functionality(ViewModel)
You do not need an update method. Use properties that access the data model and persist to the data storage(xml, database etc.) if needed.
You do not need an update method.
You should not have to do anything inside of ViewModel.cs. Only code that modifies the view should be in the codebehind. The only ViewModel you should ever access in a view is one that follows the form of MainWindowViewModel, which is more like an ApplicationViewModel that carries instances of other required viewmodels.
Finally, don't get stuck using an overcomplicated MVVM "framework" as most of the functionality is not useful or necessary.
Like stated in Yuris comment, you should not use any update method, but rather implement the INotifyPropertyChanged interface. Like the name says this notifies all subscribers when the value of a certain Property changed.
This is a nice article which contains code to a minimalistic MVVM implementation. If you have trouble implementing the pattern from scratch, try to start with this example and replace the existing classes with your own one-by-one.
As to the update mechanic inside your MainWindow.cs - you don't need any, if you specify the DataBinding in your xaml code like it is done in the example linked above.
I hope this helps you getting started!
I have the following data and objects in my program.
A DynamicObjectContainer that contains the following objects.
MeasurementParameters : DataContainer (DataContainer is the base class)
This MeasurementParameters object has many public properties, whose names I know only during runtime. I have also set up internal wiring in the DataContainer base class such that, I can access the values of the properties contained in the MeasurementParameters class using an easy to use interface.
Ex : Say I have a property in MeasurementParameters named as "pumpspeed" (type string). I can access the value of that property using this function.
MeasurementParameters.GetStringValue("pumpspeed");
I have achieved this by creating lists of delegates internally in the DataContainer object using reflection during construction of the object. (This is a one time thing.)
So far so good.
Now I am stuck at the point where I want to display these values within MeasurementParameters in a windows form.
Since I only know the property names at runtime, I have to provide the user with some method to map the property names (defined only by him in a script file) to the fixed labels within the form. So the user saves the mapping data to the table in the following format.
Entry : "pumpspeed" "label22"
I want a fast and efficient method to fetch this mapping from the database, fetch required data from the MeasuremetParameters object and display it in the windows form.
NOTE : If this is a one time operation, I have many solutions. The problem is two fold.
There are a huge number of properties in the MeasurementParameters (at around 200)
The MeasurementParameters object contains functions that update it's properties continuously. SO My windows form has to call those functions to update the MeasurementParameters object data, fetch the data and display it in the correct labels.
ALSO, this should happen in cycles of around 2 -3 times a second. (ideally)
Can anyone help me in architecting a solution for this?? A general object structure and relationship advice will also be helpful to me.
I can post the code I am using if required.
Not seeing a huge problem here
So you have Table ObjectID, PropertyName, ControlName
On opening the form / selecting the object, query them out
Build a Dictionary Keyed by PropertyName with a Value of the Label (looked up by the name of teh control from the query MyForm.Controls.FindByName(Somename). Add an OnPropertyChangedEvent to your class that throws up the name of the Property in event args then add a handler on the form
Mappings[e.PropertyName].Text = Object[e.PropertyName].GetStringValue;
Might have to twidlle with it to deal with say display controls that aren't Labels, or Panels on the Form, but it should just batter away.
I've always heard that you should separate GUI/Data/Logic components, like the MVC pattern.
So, I am wondering: In a GUI application, where do you actually store the data?
Here is an example (using C# terminology):
Suppose you have a GUI that takes user input, does some analysis, and displays results in a table. The user can have several analyses in one window, so there is a ListView at the bottom that allows the user to select which analysis is currently displayed (the selected item gets displayed).
In order to display this, the analysis data must be stored somewhere. I have always done one of two things:
Put all the data into a single object and store it in the ListViewItem's "Tag" property
Extend "ListViewItem" and just add whatever properties I need.
But, this means I am storing the data inside of the ListViewItem.
Is there a more appropriate place to keep track of the data?
I could add it as private members to the main form, but that seems like the same thing.
The only other thing I can think of is to make some global class that I can reference whenver I need to.
Thanks.
As I understand, you have some ListViewItems. Each ListViewItem is associated with your business logic object and after select one of ListViewItem you want make some operations over this buisness object. In similar situations I usually make Data Object like
struct MyDataObject
{
string Id;//very often data object need to have Identifcator, but not always
//some fields
}
and add to data object constructors for typical user input.
After that I make business logic layer contains available algorithms for this data objects. For simple projects, this is a static class like
static class MyDataObjectOperationService{
void MakeSomething(MyDataObject myDataObject);
object GetSomething(MyDataObject myDataObject);
...
}
For big projects that is usually interface. Also I usually make a data layer interface for getting this data object. For example
interface IMyDataObjectRepository{
IList<MyDataObject> GetAll();
MyDataObject GetById(string id);
//CRUD operations if it need
}
After that I put into ListViewItems ids of Data Objects and on ListViewItemClick getting selecting id, after that getting DataObject by Id using data layer classes and make some operations using business logic layer classes. If I need to save DataObject changes or create new DataObject I using data layer classes.
I've created two classes in business layer.
the first one is called Users with id (int), pass (string) and privileges (Privilege) properties and the second one is called Privilege and has id (int) and privilegeName (string) properties.
I've a method that returns all the users, and I use a repeater (actually I bind it to a DataList to auto create the ItemTemplate for me and then use a repeater) and it works and displays all the properties well except for my List property. it generates instead something like this System.Collections.Generic.List`1[WebApplication2.Public.BLL.Users]
I want to display it in a friendly way like "User Privileges : Privi1, Privi2" but still I want to keep the layers of my application clean and structured, for example I won't store them in a database in the same table and just store them as a text and append it.
I hope to find a simple and good solution...Thanks in advance guys =)
PS : I don't want to display the object Privilege, I want to display privilege.privilegeName
When using repeaters, there are two approaches, one is the one suggested by Bugai13: to have a custom property that displays it. This is fine for certain types of nested data.
Your other option is to just have a repeater inside a repeater, and bind it appropriately (to what would be a list assigned to your main data object, depending on how you O/R Mapper works).
You can have the code for the custom display property not in the data model, but in your presentation layer somewhere (depending on your framework/design), so it's not a "bad" thing to do that. It's up to you, with whatever "feels" best.
Just create property at your Bussiness object, and bind it:
public string PrivilegiesString
{
get
{
var sb = new StringBuilder("User Privileges : ");
foreach(var item in privileges)
{
sb.AppendFormat("{0}, ",item.privilegeName);
}
return sb.ToString();
}
}