For last two years I started diving into programming with C#. After reading and watching tutorials I tried to make my own app but I'm stuck at the point to get everything glued together.
I have a MainWindow with a TabControl. The first tab is an Overview and works fine with my Model and ViewModel (BaseViewModel implemented with RaisePropertyChanged() calls).
The next tabs are more or less independent to eachother but they have multiple UserControls in there.
The UserControls are not only plain collections of TextBoxes and Buttons but also have (editable) ComboBoxes and ListViews which filled up by other Models.
XAML Pseudo-code:
<MainWindow>
<Grid>
<TabControl>
<TabItem1> Overview ViewModel </TabItem1>
<TabItem2> UserControl1 </TabItem2>
<TabItem3> UserControl2 </TabItem3>
... etc
</TabControl>
</Grid>
</MainWindow>
A UserControl can occur at least once or multiple times inside a TabItem (via Button Command, add/remove to/from ObservableCollection). Inside that UserControl a ListView (or another approach) can be filled with data bound to an underlying model.
I already tried to implement my UserControls with registered dependencies but I don't see how I could register a ListView inside the UserControl to be able to bind to it. So I switched to another approach of having a separate ViewModel for each "parent UserControl". At this point I'm also stuck because I cannot be sure the "child UserControls" or models are a subset of the parent UserControl.
So somehow I'm doing something wrong but I don't see what exactly.
I hope someone can provide some hints.
EDIT:
I've put an overview on how my data should be represented.
General Overview for Models in UserControls
Any ideas on how to implement those structures are welcome.
I'm new to c# and mvvm.
I have a class that has many properties, and because of that, it is not possible to present every property to user in one page. Therefore, I decided to break the UI into 4 different part. I designed one user control for each of these parts.
As of now, I have 4 different user controls which are presented to user with the help of a side bar selection.
However, I still have one object to work with and it is not possible to break the object too.
The problem is I cant access to object from user controls' code behind. It means that I can bind object with UI but I'm not able to change parameters in code behind.
Welcome to SO!
On one hand you talk about MVVM and data-binding, but then on the other hand you talk about modifying changing parameters in code-behind. These are antithetical design patterns. Pick one!
If you are implementing MVVM then, as you know you have the View (UI e.g. Page1.xaml) in XAML, with code behind (Page1.xaml.cs) these then use a ViewModel (e.g. Page1ViewModel.cs) as their data context, i.e. where they can access the Model.
You do not have to have a one-to-one correlation of Views, ViewModels and Models.
You can have more than one View use the same ViewModel as its data context and you can have a ViewModel contain yet more ViewModels and a ViewModel can reference several Models if required.
So in your situation I'd have several pages reference the same ViewModel.
How is this possible for WinRT?
I have read the answer for WPF How to programmatically click a button in WPF?, but does not really help me.
Anyone solved such an issue?
First, I'd like to say if you want the button to "appear to have been pressed (in terms of animation/highlight effects) this won't help you but otherwise it should.
My Advice to you would be to follow the Model-View-ViewModel (MVVM) design pattern when designing your application if you haven't already. That way instead of calling the "button" click you can simply execute the method in your viewmodel that would normally be bound to that click.
Example:
You create a model class representing data in your database.
You create a view (page/window) with buttons and other UI elements on it.
You create a ViewModel class that has a series of public methods and collections.
Now in the XAML for the View, you bind the ViewModel as your DataContext and bind the public properties of the ViewModel to your collections (ItemSource for a ListBox being bound to an ObservableCollection is on example). You can create public methods that are "commands" and bind them your buttons so that when the button click event is fired, the command in the view model is executed. Now for all your unit tests and for any other reason you might want to programmatically "click" the button, you can simply call the associated methods in the ViewModel and never worry about what the actual View is doing.
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.
http://s7.directupload.net/images/140511/66z6w2tq.jpg
As you can see on the picture I am explaining everything with a Schema, I have a TabItem and on this TabItem I want to change the DataContext everytime with a Button. What I mean,is that I want to navigate through different UserControls but to stay on the same TabItem from a TabControl. I dont know how to Navigate through different ViewModels and everytime my values not to change from my Elements. I also could not find an Example of the same situation. Any Help with a Code Snippet or a full example will be appriciated.
Thanks in advance.
WPF/MVVM
I think this is a good case for using pub sub with EventAggregator or MvvmLight's Messenger.
You can then loosly coupled notify the MainViewModel to exchange controls or views within a tab.
Basically you can notify another ViewModel with another scope to do certain changes and then subscribe to it.
A possible structure could be:
- A MainViewModel with a collection of TabItemViewModels
- A single TabItemViewModel could contain also Controls and nested ViewModels
If you want to change a tab send a ChangeTabMessage to the MainViewModel
If you want to navigate within a tab use also Messaging or navigate as you do today.
Check out the EventAggregator here: http://msdn.microsoft.com/en-us/library/ff921122.aspx
or check out MVVMligh Toolkit Messenger ...
HTH