简体   繁体   中英

In Xamarin.Forms, how to allow for autocompletion for bindings in XAML code in the case you can't instantiate the BindingContext from XAML?

Given the following project:

MainPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
    x:Class="A.MainPage"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:A">
    <ContentPage.Content>
        <StackLayout>
            <StackLayout>
                <Button Clicked="Greet" Text="Greet" />
            </StackLayout>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

MainPage.xaml.cs

using System;
using Xamarin.Forms;

namespace A
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }

        private void Greet(object sender, EventArgs e)
        {
            Navigation.PushModalAsync(new SubPage
            {
                BindingContext = new SubPageViewModel("World")
            });
        }
    }
}

SubPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
    x:Class="A.SubPage"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
    <ContentPage.Content>
        <StackLayout>
            <Label
                HorizontalOptions="CenterAndExpand"
                Text="{Binding Greeting}"
                VerticalOptions="CenterAndExpand" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

SubPage.xaml.cs

using Xamarin.Forms;

namespace A
{
    public partial class SubPage : ContentPage
    {
        public SubPage ()
        {
            InitializeComponent ();
        }
    }
}

SubPageViewModel.cs

using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace A
{
    public class SubPageViewModel : INotifyPropertyChanged
    {
        private string place;

        public string Place
        {
            get => place;
            set
            {
                if(place != value)
                    return;
                place = value;
                OnPropertyChanged();
                OnPropertyChanged(nameof(Greeting));
            }
        }

        public SubPageViewModel(string place)
        {
            this.place = place;
        }

        public string Greeting => $"Hello, {place}";

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Visual Studio won't autocomplete bindings in SubPage.xaml and will be complaining that it "Cannot resolve symbol 'Greeting' due to unknown DataContext", because the syntax highlighter doesn't know the type at the compile time. Typically, I'd use the following syntax:

<ContentPage.BindingContext>
    <a:SubPageViewModel />
</ContentPage.BindingContext>

however, this isn't applicable here, since the ViewModel is not default constructible.

If this was WPF, I'd be using mc:Ignorable="d" together with d:DesignInstance , however, DesignInstance doesn't seem to be implemented in XF.

How do I make autocompletion work?

You can declare a dummy static property which will be used in a binding.

SubPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
    x:Class="A.SubPage"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:a="clr-namespace:A;assembly=A.Android"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    BindingContext="{x:Static a:SubPage.BindingContextDummyInstance}"> <!-- <------ added -->
    <ContentPage.Content>
        <StackLayout>
            <Label
                HorizontalOptions="CenterAndExpand"
                Text="{Binding Greeting}"
                VerticalOptions="CenterAndExpand" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

SubPage.xaml.cs

using Xamarin.Forms;

namespace A
{
    public partial class SubPage : ContentPage
    {
        public static SubPageViewModel BindingContextDummyInstance => null; // <------ added

        public SubPage ()
        {
            InitializeComponent ();
        }
    }
}

This changes nothing with regards to code semantics since the default BindingContext is still null , but now autocompletion is working, because the BindingContext is known at compile time.

You can try:

<ContentPage.BindingContext>
    <x:Type Type="a:SubPageViewModel " />
</ContentPage.BindingContext>

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