I am new in wpf and there is something that I don't understand..
Everywhere I am reading about separation of code and UI. So how should it work, even if I can design everything in blend, my code behind has always to react on changes and change visibilities in other situations... So first thing without the names of the controls, the code behind won't compile... And even if I have the names, isn't it far impossible to coordinate this?
What you've described is a typical approach for WinForms where achieving a real separation of UI and logic is not possible as the application is driven by events hooked to specific controls.
However, in WPF you do not use (or don't have to use) events for the communication between UI and the application logic. Main areas worth investigating for you are:
DataContext
Binding
Very broad overview is that the XAML describes the layout and specifies where the layout should get data from. Proper data are present in the data context and the WPF engine is responsible for all the wiring (or the binding).
<TextBlock Text="{Binding Caption}" />
For instance in the code above the Text in the TextBlock will be populated with the value stored in the Caption property in the data context. (Usually the data context is specified on the level of a user control or user window.)
In the code behind there is nothing that is related to the TextBlock or to populating it with the values.
What you will find in the code behind usually is only initialization of the DataContext:
public partial class MyUiClass
{
public MyUiClass()
{
this.Loaded += (sender, e) => { this.DataContext = new MyViewModelClass(); }
}
}
All the data are stored in the class set as a data context (MyViewModelClass in the example above).
As a next step I would recommend to go through some MVVM tutorials (there is quite a few good ones on YouTube).
In the context of the "separation of code and UI" discussion, you aren't separating the Xaml from the Code-Behind. Rather, you are separating the logic from the Xaml and, as a result, separating the logic from the Code-Behind as well.
When a Xaml control is constructed, not only is the xaml "view" constructed but so also is the backing partial class that initializes the control. As a result, you always have a code-behind. It's a fundamental part of how Xaml works.
There is something wrong in architecture you're talking about.
You don't need names of control in the model data. The only thing model data interacts with are events/commands. In that way you have a separation between presentation and data where the model view is a bridge between those two.
Related
I have been following this tutorial on MVVM pattern using caliburn micro
https://www.youtube.com/watch?v=laPFq3Fhs8k
What is the difference between .xaml.cs and ViewModels/ViewModel.cs ?
I see we put our code for the shellview in ShellViewModel.cs, but when I, for example, choose an event handler for a Button, visual studio takes me to .xaml.cs and not to the ViewModels/ViewModel.
Do I have to stick to one or each file has a different role/responsibility? ( considering that I want my code to still be following MVVM pattern )
Files ending in .xaml.cs are what is called the View's "code-behind". Anything inside this file is tightly coupled with the View.
If you want to follow the MVVM pattern, you will code almost all of the interaction of the UI with your Models (example: click of a button change some data or get some data from the database) on the ViewModels (.cs files), which are independent from the Views.
The only link between the View and the ViewModel is that the ViewModel is the DataContext of the View. In other words, the View knows about the ViewModel, but that ViewModel does not know anything about the View.
Event Handlers are not generally used in a MVVM world. You need to use Commands. But that is a whole other question/answer.
The important thing to keep in mind is that MVVM comes to address, mainly, two things: the Separation of Concerns (UI vs UI Logic) and Testability of your software.
I'll start by suggesting that you learn the basics of the UI framework you're using (WPF, etc.) before adding an additional framework on top of it. I've seen that this only makes the learning curve steeper.
With that said, the .xaml.cs file is what is commonly referred to as the code behind. This is the code that "controls", so to speak, the UI. You'll note, for example, that these are all "partial" classes because there's going to be some auto-generated code when you compile that does view-specific things like bindings, etc.. The xaml.cs file should be used sparingly and only when you need to know or operate on specifics of the View itself.
With MVVM, you'll often see code behind classes that are almost completely empty, with just a constructor present. The logic in these cases is moved to a "View Model" class which provides a link between the View and the Model (take a look at this SO post for a more thorough description). You should bind to objects in the View Model, and use it as the data context for your view. It contains all the logic to define how the view effects your model.
So - applying this to event handlers... An event must live in the code-behind, because you can't explicitly bind to one in your VM. You could easily call the function you want by accessing the ViewModel right inside that event handler, and there's nothing particularly egregious about this approach. That said, there is another concept called a Command that will live in the View Model itself; a command, as opposed to an event handler, is a Property, so you can bind to that in your .xaml file using
...Command="{Binding FunctionNameHere}"...
It also has nice features like being able to define when the command is valid (so you can disable your button automatically when, for example, the form is missing a required field).
For my application, I'm updating a lot of my controls to better incorporate the MVVM pattern because when I originally started the project I had never used WPF before.
My question is if it is possible to go too crazy with data binding, or should I use it almost exclusively?
For example, say I have two grids named Grid_Sample1 and Grid_Sample2. These grids are viewable based on a user clicking a button. So I have an event for that button, where I either collapse them or make them visible. Inside the event, I could write the following to hide them:
Grid_Sample1.Visibility = Visibility.Collapsed;
Grid_Sample2.Visibility = Visibility.Collapsed;
Or I could go through the trouble of binding their visibility properties:
private Visibility _grid_Sample1Visibility
public Visibility Grid_Sample1Visibility
{
get
{
return _grid_Sample1Visibility ;
}
set
{
_grid_Sample1Visibility = value;
OnPropertyChanged("Grid_Sample1Visibility");
}
}
And then toggling the visibility through the binding.
What is the preferred approach for seasoned WPF users? Is there any reason to use binding for something this simple?
What is the preferred approach for seasoned WPF users?
The latter, i.e. implementing your application logic in a view model class that is separated from the visual representation defined in the view.
Is there any reason to use binding for something this simple?
The main motivation for the MVVM pattern is that it provides separation of concerns between different components in your application which makes it easier to maintain and evolve over time. Small applications generally tend to grow bigger at some point and it won't hurt you to follow the MVVM guidelines from the very start. MVVM also greatly increases the application's testability and this is true even for the smallest application.
So may advice would be to learn and implement the MVVM pattern. It is the recommended pattern to use when developing XAML based UI applications and there is a reason for this.
Ideally, a view should just contain markup and any view-related logic that doesn't belong in the view model.
I recently started learning about WPF, which led me to learn about MVVM and eventually MVVM Light, so still a starter in these three. I am building an application with a layout similar to the picture in the link -> Application layout
In order to maintain good code separation and avoid huge files i decided the best approach would be to create a main View, and in that create several smaller Views per "zone" of the UI. From what i read in several tutorials, it is advised to maintain 1 ViewModel per View. Therefore i have a Master View / ViewModel, and several View / ViewModels running simultaneously.
Finally i have a single Model that keeps track of the information I plan to display in the UI. The Model interacts with an external API that can modify the data in it. So besides data being modified by user request (ex: pressing buttons or timers), the data will also change with asynchronous events from the API. Which means I need two way communication between the Model and the ViewModels / Views.
The questions:
1. Do you agree with the "1 view per zone of the UI"? And the 1 ViewModel per View?
2. In the Main View-Code-Behind I instantiate all the ViewModels, and in each View I bind them like in the MVVM Light examples i saw:
<UserControl ... DataContext="{Binding Main, Source={StaticResource Locator}}">
<UserControl ... DataContext="{Binding SideBar, Source={StaticResource Locator}}">
<UserControl ... DataContext="{Binding TopBar, Source={StaticResource Locator}}">
Is this the correct way to instantiate and bind several ViewModels to the respective Views?
3. Each ViewModel is passed a reference to the Main ViewModel (except the Main itself) in its constructor, which is the only one with a reference to the Model. This is how i connect the several ViewModels to the Model. Is this conceptually correct?
4. Initially i was trying to avoid using MVVM Light or other frameworks if i could do all i wanted with the RaisePropertyChanged method. I might be doing something wrong, but for example, when the Model calls RaisePropertyChanged, i can catch that event in the Main ViewModel, however it doesn't propagate to the rest of the ViewModels, so i had to do it myself by calling RaisePropertyChanged a second time:
public MountainTopViewModel()
{
_model = new MachineStatusModel();
_model.PropertyChanged += ModelPropertyChanged;
}
void ModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "TestVarModel")
{
// do something else if needed
RaisePropertyChanged("TestVar");
}
}
I'm guessing this is either not the correct way to do it, or there is a better one. So how can I inform all the Views and ViewModels when a property changes in the Model, without having to re-call the method in different places?
Sorry for the long story, i would appreciate some help.
This seems unwise to me:
The Model interacts with an external API that can modify the data in it. So besides data being modified by user request (ex: pressing buttons or timers), the data will also change with asynchronous events from the API. Which means I need two way communication between the Model and the ViewModels / Views.
I would have the async API events driving changes in the viewmodel, not the model. Then, in response to changes from the async API or from the View, the viewmodel does its usual thing: Updates the model and raises events which the view responds to. The viewmodel already plays that role, so use what you've got. Your scheme adds complexity that you don't need, and it's more complexity than you may realize. Item # 4 in your question is just the tip of the iceberg of that added complexity; believe me, it'll only get uglier from there. Don't do that to yourself. You're young. You've got everything to live for.
It's not unusual for a viewmodel to handle the PropertyChanged event of another viewmodel, or for a viewmodel to expose specific custom events which fire when specific properties change value. It might have a NameChanged event or whatever. But I don't see any particular need for that in your question, as I understand it.
1. Yes.
2. If MVVMLight does things the way you've got it there, do that. Plunkett's Razor: Whenever possible, conform to the practices of the framework you're using. Consistency is golden in programming for many reasons, and if you follow the "rules", you'll usually find the framework will be there waiting to help you instead of fighting you every step of the way. This isn't a law of nature, but it's an amazingly reliable rule of thumb.
3. That's conceptually a little shaky. Ideally, we try to write viewmodels that aren't dependent on "parent" viewmodels. Your Library viewmodel has to know what a Book viewmodel is because it contains a collection of them, but a Book viewmodel can often be more useful if it doesn't depend on a Library. Imagine writing a Wheel that's got all kinds of dependencies on Car, and then having to implement Bicycle. Do you give Bicycle an Alternator, or do you create a dummy Car? Times like that you start to daydream about moving to a commune in Vermont and making useful objects out of wood.
I would probably have a model type for each viewmodel, and give all the viewmodels a reference to their own model in their constructors. The models would probably have the same parent-child relationship as the viewmodels. If your model is Entity Framework or something instead of "POCO" classes, then yeah, one model for everybody or whatever. But still, just hand it to them directly.
I am required to use the mvvm pattern. I know that the viewmodel should not care about the view from what I been reading. As a result I don't know how to solve this problem:
I have a dll that basically turns a textbox and listview into an autocomplete control:
SomeDll.InitAutocomplete<string>(TextBox1, ListView1, SomeObservableCollection);
anyways I don't know how to call that method from the viewmodel using the mvvm patter. if I reference the controls in the view I will be braking the rules.
I am new to MVVM pattern and my company requires me to follow it. what will be the most appropriate way of solving this problem?
I know I will be able to solve it by passing the entire view to the viewmodel as a constructor parameter but that will totaly break the mvvm pattern just because I need to reference two controls in the view.
What you're doing here is a pure view concern, so I'd recommend doing it in the view (i.e. the code-behind). The view knows about the VM and its observable collection, so why not let the code behind make this call?
(I'd also recommend seeing if you can get a non-code/XAML API for "SomeDll", but I have no idea how much control you might have over that)
There are two things that I'd point out here -
First, this is effectively all View-layer code. As such, using code behind isn't necessarily a violation of MVVM - you're not bridging that View->ViewModel layer by including some code in the code behind, if necessary.
That being said, this is often handled more elegantly in one of two ways -
You could wrap this functionality into a new control - effectively an AutoCompleteTextBox control. This would allow you to include the "textbox" and "listview" visual elements into the control template, and bind to the completion items within Xaml.
You could turn this into an attached property (or Blend behavior), which would allow you to "attach" it to a text box, and add that functionality (all within xaml). The items collection would then become a binding on the attached property (or behavior).
I'm a bit confused as to what a viewmodel's role is beyond databinding. I have a menu built in silverlight. The menu has x number of menu items which is determined at runtime. One of the features I would like to add to this is that each menuitem has a different text colour when hovered over.
Is it the role of the view to have a colour selector method or should the view handle this in it's code behind?
Normally I would keep the coloring/styling in XAML if possible - My view of the ViewModel is that it is responsible for providing all the data (ie. not graphical stuff) from the Model in a manner the View can consume.
If it was complex logic that determined the color and it was to be reused - I might be tempted to put it in the ViewModel tho.
The view model is used by the data binding process as a "safe" way to allow you to sort/filter/group the records as seen by a specific control without (necessarily) making changes to the actual bound data set (that is, unless/until you tell it to). (FMI read Bea's article here.)
I agree with Goblin here, in that the presentation aspects like color might be best kept separate in the XAML, for example in the DataTemplate used by that control.