MVVM: Convert code-behind to XAML - c#

I've got an AllTopicsViewModel and its got a property ExerciseVM which is an AllExerciseViewModel, since I want to be able to refresh the AllExerciseViewModel of an ExerciseView so I am doing it like this (not even sure if it violates MVVM, pls. tell me). Well, I want to convert the 2 lines following the InitializeComponent to XAML but not sure how, can anyone help me out?
public MainWindow()
{
InitializeComponent();
AllTopicsViewModel vm = (AllTopicsViewModel)topicsView.DataContext;
vm.ExerciseVM = (AllExercisesViewModel)exercisesView.DataContext;
}

Yes, this is a misconception, according to the idea of MVVM.
Ideally, your View's codebehind (view.xaml.cs) contains nothing more than the auto generated code. Your view only accesses the ViewModel via WPF's data binding mechanisms. Because data binding via WPF is a loose coupling between the binding view and the bound-to ViewModel, you achieve the seperation that drives people to use MVVM.
You are retrieving the ViewModel in the Views codebehind from your control's DataContexts. With this, you create a strong reference between View and ViewModel. So, to help you with your question: You should think about what you are trying to to do with your ViewModel in the View's codebehind and how you can do it differently, either in the view's XAML or in the ViewModel's code itself.
If you like, post the complete MainWindow() class for some advice...
EDIT:
Ok, so its just about setting the child ViewModel on the parent ViewModel. The parent ViewModel AllTopicsViewModel should be responsible for setting its own ExerciseVM on initialization. This is not the View's job. the parent viewModel should assemble the data from one or more models and then create the child view models which the view consumes. Does that make sense for you?

Related

How does MVVM fit into WPF when you must refer directly to a control

I'm new to WPF and I'm attempting to incorporate MVVM design pattern into my projects. In all the MVVM examples I've seen, the MainWindow.xaml.cs is only used to set the DataContext to the view model.
this.DataContext = viewModel;
Everything is very neat and decoupled away from the UI. events were also replaced with commands. There are two questions that I have regarding this.
I'm wondering about how you are supposed to hook up controls that don't have the command property.
What am I supposed to do when I would typically interact directly with a control e.g. Perhaps I want to set a combobox's index to -1. How am I supposed to do this on the view model?
The collected comments by #EdPlunkett, #Clemens and #BionicCode answered my questions.
To Summarise:
I can interact with controls by binding to their properties through INotificationChanged and ObservableCollection
Elements that don't have a command property can still have properties bound to an ICommand property in the viewmodel.

ViewModel into View

Currently I'm learning C# with WPF. My mainapproach is to use the MVVM pattern the best I can but now I'm a bit confused.
In my Application for all my views I have a viewmodel:
private DruckviewViewModel ViewModel { get; set; }
public Druckview()
{
ViewModel = new DruckviewViewModel();
DataContext = ViewModel;
InitializeComponent();
}
Is this the suggested way to implement the ViewModel into the View or are there better ways to do it?
MVVM doesn't mean no code-behind.
MVVM is the pattern of separation of concerns. It helps to separate your application's architecture to the three parts(in order of appearance):
Model
View
ViewModel
Where Model is class containing your business logic.
View represents your view class which contains only view related logic(XAML and code-behind) It is Ok to have code-behind unless code contains only view's logic (for example in button click eventhandler you copy color of one textbox to another, which of course can be done in XAML, but from MVVM point of view it is not important)
ViewModel represents View's behavior without any reference to the View.
Notice that for example this property on my opinion will violate MVVM pattern, because Visibility is view related type
public Visibility MyVisibility { get; set; }
So dependencies between parts of MVVM goes like this:
Model doesn't know about anything
ViewModel know only about Model
View know about ViewModel
View ---> ViewModel ---> Model
I think for using MVVM is not important how tightly View bounded to the ViewModel. It is already bounded, because you use ViewModel's properties and commands.
Not bounding tightly (for example using interface as ViewModel) will give your possibility to test View without real ViewModel by creating own "design-time" viewmodels for example.
If your current solution works and satisfy your needs and you just starting with MVVM and WPF then continue with that until you meet need to fully isolate View from ViewModel's types
This will work, but it isn't really true to the MVVM pattern, as the View is now directly tied to the View Model.
Most existing MVVM frameworks use the concept of a View Manager. A class that creates a view from a view model instance, connects them together, and displays the view. You would end up with something like this:
DruckviewViewModel vm = new DruckviewViewModel()
ViewManager.Instance.DisplayViewFor(vm);
It would figure out, based on naming conventions, that DruckviewViewModel uses the Druckview. It would create the view, set the DataContextProperty, and make the view visible.
Without using one of these frameworks, this is a lot of work to build on your own, but this is considered a "Best Practice" pattern.
You may want to consider using an existing framework, a good list comparing their features can be found here.
BTW, if you are wondering how to get intellisense in the XAML designer without setting the DataContext in the constructor of the view. The proper way to do it is to add a design instance in XAML, with an attribute like this.
d:DataContext="{d:DesignInstance local:DruckviewViewModel}"

WPF MVVM Change Model

I have a UserControl where the data gets passed in via a dependency property.
The UserControl is backed by a view model and the data is assigned to a property of the view model.
The XAML binds to both properties in the view model as well as properties within the passed in data.
The problem is if the user changes the data then databinding with the UI breaks. The UI is still bound to the original data object.
How can I cause the binding to get refreshed? INotifyPropertyChanged is implemented throughout, but it is not the property that is getting stale, but the binding. Basically, how do you go about replacing a backing model?
Since I'm not sure my description is clear I will try to describe it again in pseudo code.
<MyControl Source="{Binding Data}"/>
Where source is a dependency property of MyControl. In the PropertyChangedCallback this data is handed to the view model.
MyViewModel.Data = Source;
Within the MyControl XAML things are bound to this model.
{Binding Path=MyViewModel.Data.Item}
If you are wondering why the dependency property is defined in the UserControl, it is because it is a reusable control and the end user should not know about the view model.
"The UserControl is backed by a view model" and thus breaketh the application.
The UserControl's DataContext should be the Model. Period. If you need to perform UI logic, do it in the codebehind. Need something else? Create DependencyProperties on the surface of your UserControl to supply them.
When you create a ViewModel specifically for your UserControl, you break the natural flow of the DataContext (at this point, probably the Model the UC is designed to work with) and binding within the UserControl. It's pointless in most cases and harmful in some (as you have noticed).
My canonical answer on the subject contains more details.
Are you trying to swap-out the DataContext of the usercontrol during an application's session?
If you are, then I am fairly confident that this will not work.
Have you considered spinning up a new instance of that user control with the other DataConext?

inheriting object from another class

So currently I have a RadAutocomplete box. I am able to call that object in the
public MainWindow()
But I want to be able to call it in my viewmodel. If I may get tips and suggestions Would be great.
Never in WPF create UI elements, like in your case telerik objects, from view model.
If you do so, you loose benefits of MVVM.
View model is for binding between UI and business logic itself. You have to define telerik oject in XAML and show/hide it based on model view property.

How to access another control's viewModel

I have a CustomControl B, which uses a DataContext/MVVM (viewModelB). Now I want to bind one Property of my CustomControl to another control A (uses viewModelA as DataContext).
So I have two Ideas:
Whenever PropA in viewModelA changes, I could directly update PropB in the viewModelB. But this creates a dependency between the viewModels, which seems ugly to me. Or is this a common way in the MVVM pattern and can't be avoided?
As an alternative I could think of a dependency property on CustomControlB and wire it to CustomControlA's viewModel by a binding, something like that:
<myControlB PropB={Binding ElementName=myControlA, Path=DataContext.PropA} />.
So far so good, but the dependency property is defined on the view now. How should I visualize it?
a) Should I transfer the value (from the property wrapper) to viewModelB and bind to it from viewB's XAML code?
b) Or should I directly update the view from B's codeBehind? Would this be still a proper MVVM "style"?
Which of the options would you recommend?
regards
Andreas
As long as ViewModelA doesn't actively update ViewModelB, there is no real coupling between the two viewmodels. What I mean is that if your main view model (which knows both viewmodels) is the one that wires up the binding, the view models are still loosely coupled.
So to me any of these are fine:
Bind directly to myControlA.DataContext.PropA from XAML
Have the MainViewModel register for ViewModelA's property changed event and modify ViewModelB's property as necessary. Here MainViewModel knows about the two view models, but they know nothing of each other.

Categories