Binding single control to different Datacontext in wpf - c#

I have a button button_extract. I want to bind it to two different data contexts (2 classes in different namespaces)
I want to set the Command and IsEnabled properties to different data context.
I have one datacontext set for Command property. But how to I specify the datacontext of IsEnable property which is in different class and namespace. Here is the scenario:-
I have a project named Environments with three namespaces:Viewmodel,Data and View
Viewmodel has class A
Data has class B
View has xaml C with button button_extract.
The data context for C is set to class A.The xaml is as follows
<UserControl x:Class="Enviornment.Views.C"
DataContext="Environment.Viewmodel.A">
<Button Name="button_extract" Command="{Binding ExtractButtonClick}" IsEnabled="{Enviornment.B.SelectedEnvionment}" >Extract</Button>
The above code does not work. The binding of IsEnabled throws error. How can I set the datacontext of IsEnabled to that of Enviornment.B???

You seem to have a common misconception about WPF regarding the need to set the DataContext. In fact, there is rarely any need to set a DataContext on any control as typically the Window has had its DataContext set and each control's DataContext will automatically inherit from that.
So, how to data bind to two different places? Generally, one place would use a normal Binding Path and the other would use a RelativeSource Binding Path. However, that would be more for the case where you wanted to data bind to properties of the set DataContext and properties of a control's code behind.
It is more common in your scenario to simply prepare a view model. That is a custom class that implements the INotifyPropertyChanged interface and provides all of the properties and functionality that your Window, UserControl, or 'view' requires. You would then set an instance of this single object as the DataContext.
Therefore, simply add properties of the relevant classes into your view model and then you will be able to access them all using the one single DataContext object. Please search online for MVVM for further information.

Related

Is there a way in .NET MAUI use multiple components components in one place?

I have a view which has some state and based on that state we want to use dynamically one of 3 component to show.
I know that we could allways hide 2 of them and show only one, but I am looking for a way to create property of in parent viewmodel in which would be stored instance of particular view we want to show. So whenever I would change that property, it would rerender itself with new component.
My main downfall is that I have no idea how to render property with stored view in XAML.
I was looking in microsoft docs, but honestly i have no idea what to look for.
If I got your issue right, what you're looking for are data templates
A DataTemplate is used to specify the appearance of data, and typically uses data binding to display data.
Since in your case the appearance (i.e. the data template) depends on the data to present, you will need a data template selector
A DataTemplateSelector can be used to choose a DataTemplate at runtime based on the value of a data-bound property.
I will try and come up with an example and might edit this answer later to present the example.
You could create multiple ContentView components with xaml UI and bind them with their own ViewModel. Then on the page you want to display your custom component create generic ContentView element and bind it's Content to ViewModel property.
<ContentView Content="{Binding Content}"/>
Then in your ViewModel create ObservableProperty using MVVM community toolkit or just implement INotifyPropertyChanged.
[ObservableProperty]
private ContentView content;
Now you can get your prepared components using Dependency Injection.
private readonly CustomView1 _customView1;
private readonly CustomView2 _customView2;
public ViewModel(CustomView1 customView1, CustomView2 customView2)
{
_customView1 = customView1;
_customView2 = customView2;
}
Now you can simply change your displayed Component in your ViewModel by changing your binded property "Content"
Content = _customView1;

Setting property of child viewmodel from parent

I have a view that I'll call View1 that has a nested user control that I'll call View2. My main application creates and shows View1 which in turn creates View2 since it is a user control on View1. Both View1 and View2 have their own viewmodels. What I need to do is get a value from View1's viewmodel to View2's viewmodel.
View2 is meant to be a completely self-contained control with its own functionality that is reusable in any other view, but it needs a piece of information from whatever view it is contained in. In the case given here, that would be View1.
My first attempt was to create a dependency property on View2 so it could be set in View1 like so:
<myUserControls:View2 MyProperty="{Binding RelativeSource={RelativeSource Self}, Path=Parent.DataContext.MyProperty}"/>
This works to set the dependency property, but that doesn't help to get the property value into View2's viewmodel where I can work with it.
I am doing this in Silverlight, if that makes any difference.
Anyone know if there is a way to do this?
I would recommend using the "Mediator" pattern, or some sort of communication between viewmodels. I personally have used galasoft MVVM light messaging to great deals of success. Rachel has also written a pretty good blog on navigation: Rachel's MVVM blog
But I would try and decrease the coupling in your program by letting the messaging handle the data context switch and viewmodel updates as opposed to creating a dependency property.
You could for instance have a baseviewmodel class which all view models inherit from, and use a polymorphic generic "view model" property which is of type baseviewmodel in your main viewmodel. Once the message was received to switch from viewmodel #1 to viewmodel #2, call a "update model" function (which you have declared in your baseviewmodel and override in your VM #2) which will then handle updating your VM #2.

C# extending a class in MVVM design pattern (WPF)

I have a View that contains a GridView object and a ViewModel that the View represents. Now, I'd like to override the controls in that ViewModel so that I keep the same GUI but with different business logic (i.e. contained within the ViewModel). What's the proper way of doing that?
I'd assume it is not as simple as extending the ViewModel since there's the issue with its GUI being represented in the View (which has a XAML component).
Any thoughts?
Thanks.
Edit: Fixed typo
What I tend to do, is create a Base ViewModel Class with the standard UI and Control logic in it.
I then set whichever Functions / Subs I want to control individually to overrideable. But I populate them up with default code, such as The standard Form State (Editting/Adding/Deleting) code. Any I want to force to be Overridden are set to Must Override of course.
Then, I create a Individual View-Based ViewModel, inherit from the Base ViewModel Class, override the methods I require, and set this Individual ViewModel to be the DataContext for the View.
You can switch in which ever ViewModels you like using this method, so long as they all inherit from your base ViewModel class.
I hope this helps!

How to implement WPF ValueConverter that needs data from viewmodel?

i am writing an application that has a viewmodel and a usercontrol that displays
data from this viewmodel. The viewmodel contains an entity "Appointment", and those
appointments have a property "UserName".
When I display the appointments, I want to use a value-converter to get a color for
the user (depending on "UserName"), but the colors are not contained in the entity "Appointment", so I wanted to create a value-converter that uses the entity "User" from the viewmodel.
What is the best way to use another entity from the viewmodel inside the converter?
Is it possible to access the viewmodel from the usercontrol? I tried to place the converter inside my viewmodel-class, but can I access this class from the usercontrol?
I figured out that the following possibilities might work:
Adjust the viewmodel so that each appointment also contains the color. But I don't want to do this because I don't want to mess with the viewmodel.
Set the converter-parameter from the class that also contains the viewmodel at startup. (Does this work?)
Use x:Reference to databind the converter parameter to the viewmodel that is unknown at compile-time.(Is this possible?)
Converter parameter is the way to go.
Why is the viewmodel unknown at compile time?
Bindings are not compile time checked anyway.
Is the UserControl.DataContext being set to an instance of Appointment, you should be able to set the parameter to {Binding UserName} or {Binding Appointment.UserName} depending on exactly what you are setting as the DataContext on the UserControl.
I would suggest that you re-examine your reluctance to modify the view model. The purpose of having a view model in the first place is so that everything that the view needs can be found in one place. Coming up with elaborate value converters to prevent modifying the view model is an approach that gets increasingly unmaintainable the more you do it.

WPF MVVM and nested Views with dependency properties

I have a parent view that defines a child view in Xaml. The child view has a DependencyProperty that is bound to the parent view's ViewModel. However, that value is also needed by the child view's ViewModel.
<custom:Parent>
<custom:Child ChildId="{Binding ParentFooId}" ... />
</custom:Parent>
ChildId is implemented as a dependency property of the ChildView control. If the ChildViewModel needs ParentFooId, what's the proper MVVM way of obtaining it?
I don't want to cast the DataContext of the ChildView into a ChildViewModel and set value in a OnChildIdChanged handler of the ChildView. That doesn't seem very MVVM-ish to me.
The other alternative I thought of was to create a new ChildViewModel with the value and set it as the DataContext in the OnParentFooIdChanged event (in the ParentViewModel); but that doesn't seem quite right either, since the ViewModels are supposed to be oblivious to the View (and thus don't know anything about DataContexts).
It seems like I'm missing something obvious...
If I understand the question correctly you just need to create the child view model within the parent view model, passing and keeping a reference to the parent view model. That way you can reference any property of the parent view model from the child view model and bind to either in the child view.
If you are simply trying to pass data from a dependency property to your view model I would use the PropertyChangedCallback event. Add a handler that sends the changed data to your View Model. I may be misunderstanding your intent though.

Categories

Resources