MVVM for a silverlight page with dynamic input controls - c#

Say you have a xaml page that takes two inputs such as DATE and some TEXT value and displays the result on a DataGrid, its easy to have a class with with 3 properties of dataTypes DateTime, string and some Collection and implement the same in MVVM.
I have a xaml page with a DataGrid and few input controls(like textbox or datepicker) generated dynamically based on a certain criteria. I want to implement this in a MVVM pattern but not sure how to go about. Any pointers will be helpful.

In my experience, MVVM is not answer for all presentation scenarios, sometimes you just have to use codebehind or build custom control. I would suggest here building custom control that takes (binds with dependency property) object or list of objects, and generates controls (text boxes with input validation/verification, for ints, doubles, date picker, etc), and binds given object to them. In the end you will have one smart control that takes object and renders input fields, and binds to them. Your VM class would just expose object or list of objects.

It is always good to separate the view and the model; however this cannot always be done with simple data binding of simple types.
I would be looking at something like a custom control that could databind to a list of {name, value, spec} pairs when the “spec” is the logical type of control to use.
Thinking about it; that is like what a property grid does if you pass it a custom collection of property descriptors….
Devexpess has a “vertical grid” that may help, also look at 3rd party property grids.

Related

Only display certain object properties inside a listbox databound to List C#

I have a listbox that is databound to a List with a bindingsource, what I would like to obtain is that the listbox only shows certain object properties like for example firstName,lastName instead of firstName,lastName,Address,Country,...
How could I manage this?
I'm using winforms.
What about create another type which will be your exact view model and use list of this type?
my last project was a big project in winforms,and i was told that the data bound controls effectively reduce the overall performance of the application.
so the whole group had to work programmatically when adding data to a control,let it be datagrid,combo box,or any other windows control.
i would suggest you do the same too,Adding data to your Controls using code.that way you also decide what you want your clients to see and whatnot.
i would also suggest you take a look here :
how-might-i-add-an-item-to-a-listbox

How can control in the view get specific data from view model?

I have multiple of views (user controls), each with its own ViewModel. To navigate between them I am using buttons. Buttons display image and text from corresponding view model and also need column and row (because there are like 10 views: 10 columns with different number of rows each).
Right now buttons are created dynamically (I made a Navigator control for this) and for view models I have base class to hold text, image, column and row. Number of views available will be different (depends on user level and certain settings), that's why it's I need control here.
Question: how shall my control get data from view models?
Right now I have interface INavigator, defined in (lol) control itself. And view models implement it. I could go opposite, let my control to know about view models. Both looks wrong.
There is a single Navigator control what has, lets say, Items bound to a list of view models. It can cast each view model to INavigator or ViewModelBase (common for all pages) to obtain specific view model image, text, column and row. So either view model knows about control (to implement INavigator) or control knows about ViewModelBase.. And this is a problem, both solution bind tight control and view models, which is bad in mvvm.
Schematically
The way you've drawn your diagram answers your own question as to how you should structure the code for this.
What you need is one VM (let's call it MainVM) which contains an ObservableCollection<VMBase> of the other VMs (using your base type so that they can all happily live in the same collection).
Your View needs an ItemsControl (bound to your ObservableCollection<VMBase>) where you specify a DataTemplate for the Button using the properties exposed by the VMBase type only. Set the Command property in the Button to call SwitchCommand, CommandParameter is set to the item itself (i.e. {Binding .}).
Your View also needs a ContentControl bound to a SelectedVM property on MainVM which you can populate.
Implement SwitchCommand to set the SelectedVM property based on the value from the CommandParameter.
public void ExecuteSwitchCommand(object parameter)
{
var vmBase = parameter as VMBase;
if (vmBase != null)
SelectedVM = vmBase;
}
All properties mentioned here should be INotifyPropertyChanged enabled so that the View registers when they change and updates the UI.
To get the different UIs for the ContentControl, add type-specific DataTemplates for each of your specific VM types to the Resources file of your View (or if you're smart and are building a custom plug-in framework, merge the Resource Dictionaries).
A lot of people forget with MVVM that the whole point is that there is a purposeful separation of View from ViewModel, thus meaning you can potentially have many Views for a single ViewModel, which is what this demonstrates.
I find it's easiest to think of MVVM as a top-down approach... View knows about it's ViewModel, ViewModel knows about its Model, but Model does not know about its ViewModel and ViewModel does not know about its View.
I also find a View-first approach to development the easiest to work with, as UI development in XAML is static (has to be).
I think a lot of people get to wrapped up in 'making every component (M, V, VM) standalone and replaceable', myself included, but I've slowly come to the conclusion that is just counter-productive.
Technically, sure you could get very complicated and using IoC containers, create some ViewLocator object which binds a View-type to a ViewModel-type, but... what exactly does that gain you besides more confusion? It makes it honestly harder (because I've done this at one point) to develop because now you've lost design-time support first and foremost, among other things; and you're still either binding to a specific view model interface in your view or creating the binding at run-time. Why complicate it?
This article is a good read, and the first Note: explicitly talks about View vs. ViewModel. Hopefully, it will help you draw your own conclusions.
To directly answer your question, I think having your ViewModels implement an INavigator interface of some sort is probably ideal. Remember your VM is 'glue' between your view and model/business logic, its job is to transform business data into data that is consumable by your views, so it exists somewhere between both your UI and business layers.
This is why there are things like Messengers and View Services, which is where your navigator service on the ViewModels can fit in nicely.
I think the design has led to a no way out situation.
I believe that creating a custom button control where the dependency properties tie the image, the row and column actually provide a way for the page, which it resides on ,to get that information to them; whether they are dynamically created or not.
Continuing on with that thought. There is no MVVM logic applied to a custom control, the control contains what it needs to do its job and that is through the dependency properties as mentioned. Any functionality of the button should be done by commanding; all this makes the button data driven and robust enough to use in a MVVM methodology or not.
Question: how shall my control get data from view models?
There should only one viewmodel which is the page the control resides on. The control is simply bound to information which ultimately resides on that VM. How it gets there, that is up to the programmer. If the button is going to contain state data, that is bound from its dependency property in a two way fashion back to the item it is bound to.
By keeping VMs out of the buttons and only having one VM that is the best way to segregate and maintain the data. Unless I am really missing something here....
Same as others here I find it a bit hard to actually understand what you are asking, so this is quite general. The answer to the question header is simply: the Control gets the data from the ViewModel through bindings, always. You set the DataContext of your Control to the corresponding ViewModel, and from there you keep the ViewModel and the Control synchronized:
If you add an ItemsControl containing buttons to the View, you add an ObservableCollection<ButtonViewModel> to the ViewModel and bind the ItemsSource of the ItemsControl to this.
If you allow the user to dynamically add content to the View, the actual code that does it resides in the ViewModel, e.g. when the user clicks on a button "Add Button", you use the Command property to call a ViewModel method that adds a ButtonViewModel to the collection and the View will automatically reflect your changes.
There do exist complicated cases that are impossible to code exclusively in the ViewModel, I have found Behaviors to be the missing link there, but I'll get into that when you show me the specific case.
If you'd like to get a working example, please provide as much code as you can, with your exact expectations of what it should do.

Customizing the FrameworkElements used to display the contents of an ObservableCollection

So it seems like what I want to do should be straightforward, but I haven't been able to find a way to do it...
I need to display a list of objects that represent custom elements for entering data. Exactly how each object is displayed depends on the parameters of the object - so it could be a grid containing a name, description, and text box. It could be a grid with a couple labels and a dropdown. It could be an expander that contains multiple sub-objects. It could be something new that hasn't been built yet (so it needs to be extensible). Right now, I am populating this list by creating the FrameworkElement for each object and then adding it to a Grid by hand.
I would like to switch to keeping my objects in an ObservableCollection, and then binding that collection to a ListBox (or similar). That way, when new objects are added or removed from the list, the UI would automatically update itself accordingly. What I can't figure out is, is there a way to point it to my C# method for creating the custom-configured FrameworkElement for each object, so that when new objects are added the appropriate elements will be added to the UI?
Well, you're on the right track as far as wanting to use an ObservableCollection<T> and a ListBox control. Though, I'd venture to say you might want to simply use an ItemsControl since you probably don't care about selecting a particular item, but merely displaying an enumeration of items, and the ListBox would allow you to actually select one of those items.
Your problem is that you want each item in the list to display differently depending on certain criteria. For this you'll want to look at the DataTemplate and DataTemplateSelector classes.
Basically, a DataTemplate is a way of saying "I want my item to look like this.", and a DataTemplateSelector is a way of saying "I want to select this specific DataTemplate based on this criteria."
Here are a few examples on how to use the DataTemplate/DataTemplateSelector classes:
http://tech.pro/tutorial/807/wpf-tutorial-how-to-use-a-datatemplateselector
http://mikestedman.blogspot.com/2009/04/datatemplateselector.html
http://wpftutorial.net/DataTemplates.html
Seperating the presentation from the model is always a good idea. It seems like you are on the right track.
Foreach object type, you should create a DataTemplate and then use ItemTemplateSelector to select the correct template for each object type.
Good luck

"Universal" control for a property of (roughly) any type?

So I'm just wondering, as my research has yielded no results, is there any freely available control (preferably WPF) that is, essentially a "universal" control for a property of any type?
For example, say you are providing a WYSIWYG form constructor, and you want to support multiple value types - strings, bools, ints, datetimes, floats, etc. And of course, Lists of any of those types too... What I'm wondering is, is there already a control out there that, when bound to, will detect the property's type, and then render the appropriate type of control for that type. That is:
For an int, a textbox with up/down buttons and validation that it is an integer
For a datetime, a datetime picker
For a list of datetimes, perhaps a custom control that combines a listbox with a datetime picker, and that lets you add/remove datetimes as needed...
It's relatively simple to write one, I imagine, but difficult to handle all the different types effectively, and of course it couldn't handle more complex types...
Anyone know of anything?
This type of control is usually called a PropertyGrid.
Have a look at these controls and see whether they suit your needs:
WPF Property Grid
WPF PropertyGrid Control
This is not exactly a perfect solution for you, but Silverlight has a DataForm which when bound to an object of a custom type will generate a form with appropriate controls for the properties. It's not included in WPF, but there is a WPF port of the Silverlight control.
EDIT
I miss-read part of your question, making this even less of a solution for you. It still might be of some help though, so I will leave it here.
If you roll your own control, you can provide this functionality fairly easily and incorporate best-of-breed controls for performing specific tasks such as numeric editors and date combos.
We initially searched for an all-inclusive control but, like you, were unable to find one. So we rolled our own with support for more than 15 distinct data rendering types. The entire control, including comments, is only about 1500 lines and that includes a lot of functionality specific to our application, but we were also able to blend in various third-party controls.
The other approach, which we use in a different use case, is to create a common control interface (i.e. set value, get value, are you valid, etc) and then create single-purpose custom controls that implement this interface.
Then to perform mass actions on the controls, it just a matter of cycling through the containers list of controls and, if the control implements our interface, performing the interface action on that control.
This significantly reduces the amount of code that we have to write to perform otherwise standard operations across all controls.

ValueConveter or DataTemplate

I am trying to build a generic interface that can accept a List of objects and then based on the users selection of how they want to view the objects will select different ways of display the object. Currently, the user has a dropdown that allows them to choose the view type such as "Details, Previews, etc" much like explorer and then based off the selection the display should change. My first attempt at this was to create UserControls that will accept the bound object and display it, however I dont know how to convert my listitems into the user controls. My question is, is should I be using IValueConverter to convert the listitem into the type of user control I want to display, or should I be using DataTemplates and a TemplateSelector to define my different views?
Why not just use ListView and GridView? Your use case is exactly why they're there.
MSDN has a nice little sample for how to switch views in a ListView at runtime right here.

Categories