简体   繁体   中英

How to pass data from ViewModel to View code behind in Xamarin.Forms following MVVM?

So the question is pretty simple, I think:

I have a View and its associated ViewModel. I have a value generated in the ViewModel and want to pass it to the View's Code Behind , following the MVVM pattern. I know it's entirely possible, because that's basically what's happening when using INotifyPropertyChanged and Data Binding, but I want to pass the value into a variable in the Code Behind, not a XAML component.

As an example, consider something like this:

ViewModel

public string VM_String { get; set; }

View's Code Behind

ViewModel MyViewModel = new ViewModel; public string View_String { get; set; }

I simply want to pass the value in VM_String onto View_String, while following MVVM principles , so something like:

View_String = MyViewModel.VM_String;

is not what I want. I'd want those values decoupled from each other.

How would one go about doing this? Something to do with delegates / events maybe?

Thanks

You need to create a BindableProperty in your view's code-behind and use xaml to bind this property to the property in your view model. Then you can use the propertyChanged event of BindableProperty to apply your logic whenever the binding value changes.

If your view is a ContentPage, it's not possible to declare a BindableProperty in the code-behind and bind it in the xaml file of the same view. However, using an attached BindableProperty will do the job.

In the code-behind of your view (NewPage.xaml.cs):

    public static readonly BindableProperty VMStringProperty 
        = BindableProperty.CreateAttached("VMString",
            typeof(string),
            typeof(NewPage),
            default(string),
            propertyChanged: VMStringChanged);

    public static string GetVMString(BindableObject target)
    {
        return (string)target.GetValue(VMStringProperty);
    }

    private static void VMStringChanged(BindableObject target, object oldValue, object newValue)
    {
        var yourView = target as NewPage;
        var vmString = newValue as string; // or GetVMString(target)
        yourView.ApplyLogic(newValue); // ApplyLogic is an instance method in your NewPage class
    }

In the xaml file of your view (NewPage.xaml):

<ContentPage
    xmlns:local="clr-namespace:YourNamespace"
    local:NewPage.VMString="{Binding VM_String}"
...

Using attached bindable properties this way is not a common thing to do. Instead, depending on your situation, you may consider creating a custom control having the (non-attached) VmString bindable property in it. Then you can add this control like a normal control to your NewPage and bind its VmString property to the property in your page's ViewModel.

The only way the code behind can interact with a View Model is through binding the View Model to the view.

So ViewModel MyViewModel = new ViewModel; this set up the view to know about the View Model.

VariableInCodeBehind = MyViewModel.VariableInViewModel;

This is the way you would assign a variable in the code behind with a variable from your View Model.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM