简体   繁体   中英

How to bind a control to a view model when page binding context is set to a different view model in Xamarin

my content page is binded to a view model, but now I need to bind some components to a different view model. My problem is that because I have binded the BindingContext of the page to a view model, when I try binding elements to the second view model the {Binding propertyname} statement looks for the property in the view model that is binded to the bindingcontext.

so my question is this: How does one simply bind an element to a view model other then bindingcontext when bindingcontext is set to a different view model?

Things I tried that didn't work

  1. Defined the second view model. and tried binding through a static resource

code

    <ContentPage.Resources>
        <ResourceDictionary>
            <selectedDeal:DealsMViewModel x:Name="SelectedDeal" x:Key="SelectedDeal"/>
        </ResourceDictionary>
    </ContentPage.Resources>

code

 <Image
     x:Name="CompanyImage"
     HeightRequest="200"
     Aspect="AspectFill"
     Source="{Binding Source={StaticResource SelectedDeal}, Path=DealImage}" />
  1. I've put the image element into a stack layout, set the BindingContext of the StackLayout and tried binding like this:

code

 <Image
         x:Name="CompanyImage"
         HeightRequest="200"
         Aspect="AspectFill"
         Source="{Binding DealImage}"/>
     

There are two ways I made the binding work :

  1. define the second view model as a property of the first view model that is binded to the BindingContext then implement the image like this

code

<Image
x:Name="CompanyImage"
HeightRequest="200"
Aspect="AspectFill"
Source="{Binding secondViewModel.DealImage}"/>
  1. in the code behind set the image source programatically.

code

CompanyImage.Source = selectedDeal.DealImage;

But what I really want to achieve is to learn the way of doing this in the XAML part if possible! any help is much appreciated!

There are several way to achieve what you are asking... I'll explain the way I'm handling ViewModel bindings...

  1. Create new class to hold a reference to each view model with the use of the DependencyService container manager. I call this ViewModelLocator. eg:
public class ViewModelLocator
    {
        public ViewModelLocator()
        {
            DependencyService.Register<ILogService, LogService>();
            if (!DesignMode.IsDesignModeEnabled)
            {
                DependencyService.Register<IDataStore, MockDataStore>();
            }
            else
            {
                DependencyService.Register<IDataStore, DesignDataStore>();
            }
            DependencyService.Register<LoginViewModel>();
            DependencyService.Register<AboutViewModel>();
            DependencyService.Register<SettingsViewModel>();
        }
        public LoginViewModel Login => DependencyService.Get<LoginViewModel>();
        public AboutViewModel About => DependencyService.Get<AboutViewModel>();
        public SettingsViewModel Settings => DependencyService.Get<SettingsViewModel>();
    }
  1. Reference this class in your App.xaml

    <viewModels:ViewModelLocator x:Name="Locator" x:Key="Locator" />

  2. This will allow you to bind to any view model by just referencing the Locator. In the sample below, your "main" ViewModel is the LoginViewModel, but the button below is bound to the About ViewModel

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Test.Views.LoginPage"
             BindingContext="{Binding Login, Source={StaticResource Locator}}"
             Title="LoginPage">
    <ScrollView>
        <Grid Margin="10,20,10,10" RowDefinitions="Auto,Auto,Auto,Auto">
            <Label Grid.Row="0" Text="Username:" TextColor="Black" FontSize="14"/>
            <Entry Grid.Row="1" x:Name="usernameEditor" Text="{Binding Username}" ClearButtonVisibility="WhileEditing" />
            <Label Grid.Row="2" Text="Password:" TextColor="Black" FontSize="14"/>
            <Entry Grid.Row="3" x:Name="passwordEditor" Text="{Binding Password}" IsPassword="True" ClearButtonVisibility="WhileEditing" />
            <Button Grid.Row="6" Text="Login" Command="{Binding About.LoginCommand, Source={StaticResource Locator}}"/>
        </Grid>
    </ScrollView>
</ContentPage>

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