I'm writing a ViewModel library which works with my WPF Custom Controls.
My problem is that my DomainModel has a large amount of Data Types:
Cd,Pens,Gadgets,Books,ecc.
All these Data Types are enumerated with an enum (I have more or less 1 hundred DataTypes), and each data Type corresponds to a DB table.
So the idea is to have a ViewModel library which exposes one property for each data type, thus my UI controls can directly bind the properties of my viewModel. The viewModel for each property return an ObservableCollection.
For instance, if I'd like to have my combo box populated with the "Gadgets" data, in my XAML I 'll have something like :
<my:XCombo ItemsSource="{Binding Gadgets}" .... />
and in my ViewModel I'll have :
public ObservableCollection<Gadgets> Gadgets
{
get
{
//get gadgets data from my domain model
return _model.GetData(DataEnum.Gadgets);
}
}
Now, in order to do that, I need in my ViewModel one property for each enumeration value, but I'd like to avoid to put 1 hundred property accessors. I'm lazy and this can be very error prone.
I know, in c#4 we have dynamic properties, so in this way I can avoid to write 100 property accessors, but I MUST use .net 3.5 which has no dynamic properties, i cannot use .net 4 ;(
Is there anyone who has already had this problem or any suggestion?
Thanks a lot in advance.
You could try to use an indexer property which returns the respective data
public IList this[DataEnum type]
{
return _model.GetData(type);
}
Then bind it using that:
ItemsSource="{Binding [Gadgets]}"
Related
initially it looked a simple problem to me but the more I think more I am confused on what is the best way to achieve what I want.
We are making a WPF application following MVVM
so scenario is -
we have a class say MyClass which has a property of type Complex, it also has a property called Category of type int.
Public Class MyClass
Public Property Category As Integer
Public Property MyProperty As Complex
End Class
Now MyProperty can have a certain values only based on its category.
We have a list of an object which contains all possible values of MyProperty against each category.
My question is considering MVVM, where this list of possible items be placed?
should we make it part of the object like a new property which has all possible values of MyProperty and then have a check when we set the property ? or somewhere else ?
Public Property AvailablePropertyValues As IEnumerable(Of Complex)
Keeping it in object makes it real simple when we bind this object to view, as we don't have to filter the list but I know its trivial to filter lists for each item and we should not consider ease of creating view while modelling our objects.
Any ideas on how to model my object ?
I think you should have all the data that shows up on the screen come from the viewmodel via bindings, that includes the possible choices you want to select from, and the actual selected value, and then validate either through the setters (that's what i see setters to be used for, to insert custom validation logic based on the input value) or nicer, by implementing an IValidatableObject interface so you can also have UI notification of invalid values.
For IValidatableObject you can see the topic http://weblogs.asp.net/scottgu/class-level-model-validation-with-ef-code-first-and-asp-net-mvc-3 or http://msprogrammer.serviciipeweb.ro/2012/03/19/ivalidatableobject-and-idataerrorinfo/
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've been looking at the difference between a BindingList and an observablecollection and List. From what I've read, it seems like the BindingList is the only collection type that will notify if an object in it has one of its properties changed. I cannot get this to work.
I have a property on a ViewModel called Matches, which returns a BindingList created out of a list of CarMatch objects in another class. (Cars m_Cars = new Cars();) My DataGrid on the View is bound to this Matches property in the VM.
public BindingList<CarMatch> Matches
{
get
{
Return new BindingList<CarMatch>(m_Cars.Matches);
}
}
Now, in the code I change one of the CarMatch object's properties, say.. automaticTrans = true from false. Matches[0].automaticTrans = true. I want to see that change in the DataGrid. Without implementing INotifyPropertyChanged inside of the CarMatch class, is there a way to update the datagrid from the viewmodel? Using INotifyPropertyChanged on Matches does not seem to do it. There is something about this I just don't understand, and could use an example to look at.
CarMatch (not Matches) has to implement INotifyPropertyChanged. But consider using ObservableCollection unless you really need some of the additional scenarios offered by BindingList: with ObservableCollection, INotifyPropertyChanged comes for free. And, more importantly, BindingList doesn't scale well.
try
dataGrid.Items.Refresh();
but keep in mind that is a expensive call if you have lots of data and you call it several times in a short period of time.
This question is a follow-up of this older one, and it's more of a confirmation than an open question.
My ViewModel instance has a private instance of the Model, _modelInst.
The ViewModel has exclusive access to the Model's data during editing (so the Model doesn't need to implement INotifyPropertyChanged).
Now there are three ways I came up with how to edit the Model data from the View:
Getting/setting directly on the Model instance
e.g. for simple value fields
return _modelInst.fieldname;
_modelInst.fieldname = value;
This one's easy to implement...
Creating a ViewModel instance and operating on the parent's data structure
e.g. for more complex object types like structs:
Creating a new ViewModel for that type.
The ViewModel knows the parent and its fieldname.
displaying that in a ContentControl+DataTemplate
getting / setting:
via methods of the parent with the fieldname as parameter,
overwriting the whole original object even if only one field is changed
This means creating a new interface (with update routines working on _modelInst), implemented by the parent, for each of these structures.
Creating ViewModel instances with no direct knowledge of the parent's data structure
e.g. for (lists of) classes within parent classes
Creating a new ViewModel for each class
Sending update instructions to the parent via
commands
messages
reflection (parent knows which child called the function
by comparing the instance to all stored children)
All of these are a big mess implementing, creating functions for
every field of the model that is editable.
Which means pretty much all fields of the model...
(4.) One could create a generic ViewModel which works via reflection alone, where each
subobject knows its parent and its fieldname (+index, if in a list).
Only the root's logic would then interfere with the model.
But that solution would also require a means to store the path to a field within _modelInst.
Is there any other (more simple) way to achieve this?
Did I misunderstand the principles of MVVM (again)?
Is MVVM suited for manipulation of large hierarchical data structures?
Hopefully these resources will help; they helped me quite a bit as I learned MVVM and how to approach representing object graphs/hierarchies with view models:
Editable Object Adapter
Editable Collection Adapter
MicroModels
This is an excellent question for which I do not feel there is a good answer that comes stock with the MVC pattern.
ViewModels work great when the model they map to has no children.
But when the model has children, as in
Customer
-->Order
-->Country
(imagining Country were a child object of Customer) the design pattern kind of breaks down.
The best thing I've found is to use inheritance and selectively expose
only those children for which you need viewmodel logic. Otherwise, just access
the model's properties of the view that will come in via inheritance.
public class CustomerView : Customer //inherits from Customer (model)
{
public CustomerView(Customer customer)
{
this.FirstName = customer.FirstName
//etc..
//Only if you need it, that is if you have some display-specific
//logic relating to country for a given view, you create
//a CountryView class that inherits from Country and gets populated
//by an instance of it as well
this.CountryView = new CountryView(customer.Country)
}
public CountryView CountryView {get;set;} //sadly you cannot override Country but you may be able to shadow it.
public string DisplayColor
{
if(base.FirstName == "Joe")
{
return "red";
}
return "";
}
}
This gets messy when dealing with grandchildren. If anyone has a better solution, I would love to hear it.
Thanks
I want to display and edit some objects in a WPF data grid and I'm looking for a good way to do so. All objects I want to display have the same fields, but every execution the fields of my objects can differ. Here is a piece of the interface to illustrate what I mean:
public interface IMyObject
{
IEnumerable<string> GetFieldNames();
IEnumerable<Type> GetFieldTypes();
object GetField(string name);
void SetField(string name, object value);
}
How can I generate a data grid which displays this kind of objects? I thought of XAML generation to define the columns, but I'm still facing the problem of accessing the fields. I think I could realize this with value converters, another option would be to dynamically create a type which exposes the dynamic fields with properties.
Are there any other ways and which should I favor? I'm keen on hearing your opinions.
Best Regards,
Oliver Hanappi
I would do this to my interface
public interface IMyObject
{
IEnumerable<string> GetFieldNames();
IEnumerable<Type> GetFieldTypes();
//i would add this property, then you can bind directly to it.
//basically it is a collection indexer, indexed by string
object this[String name] { get; set; }
object GetField(string name);
void SetField(string name, object value);
}
I would build the columns in code like so, (where stringKeyCollection is a collection of strings returned from GetFieldNames() - although personally i would keep this information separate from my object - like a master definition)
foreach(String item in stringKeyCollection){
//create the base column (use whatever column type you want
DataGridBoundColumn column = new DataGridBoundColumn();
//create the binding for the column
column.Binding = new Binding("[" + item + "]");
//set the header
column.Header = item;
}
then you have objects in each cell of the grid and you can define templates however you wish.
The fact that the type of your bound objects changes each time is not hugely important, if your grid is set to AutoGenerate columns then it will create the columns for you. However this could lead to some rather un-pretty results.
What i would suggest is this:
with your data objects, annotate each displayable property with a custom attribute, this is simply to mark it for later inspection
once you have obtained your collection of items, take the first item in the list and pass it to a factory function that returns grid columns
the grid column factory function can inspect the data object using reflection looking for properties with the special attribute you used earlier, and create the appropriate grid column with the appropriate binding and value converter
add the collection of grid columns to the grid, and bind the data
this approach depends upon all the items in the collection being of the same type, but should be reasonably snappy.
If you have different items in the collection and they have little or no commonality then you could look to the method where you query each item for it's bindable properties and then mash the whole lot together.