Display Name
Display Name

Reputation: 15071

How to pass arguments to the view model constructor declared in Xamarin.Forms XAML binding context element?

I can do this scenario, in which I pass arguments to the view model constructor, in the page code behind as follows.

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
    {
        if (EqualityComparer<T>.Default.Equals(field, value)) return false;
        field = value;
        OnPropertyChanged(propertyName);
        return true;
    }

    protected void OnPropertyChanged(string propertyName)
            => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

public class DateTimeViewModel : ViewModelBase
{
    public DateTimeViewModel(double interval = 15)
    {
        TimeSpan ts = TimeSpan.FromMilliseconds(interval);
        Device.StartTimer(ts, () =>
        {
            DateTime = DateTime.Now;
            return true;
        });
    }

    private DateTime dt = DateTime.Now;

    public DateTime DateTime
    {
        get => dt;
        private set => SetProperty(ref dt, value);
    }
}

public partial class TimerPage : ContentPage
{
    public TimerPage()
    {
        InitializeComponent();
        var myVM = new DateTimeViewModel(1000);
        var itemSourceBinding = new Binding(nameof(myVM.DateTime), source: myVM);
        SetBinding(ContentPage.BindingContextProperty, itemSourceBinding);
    }
}


<ContentPage <!--removed for simplicity--> x:Class="MyProject.TimerPage">
     <StackLayout>
        <Label Text="{Binding Millisecond}" />
     </StackLayout>
</ContentPage>

Question

How to do the following in XAML?

var myVM = new DateTimeViewModel(1000);
var itemSourceBinding = new Binding(nameof(myVM.DateTime), source: myVM);
SetBinding(ContentPage.BindingContextProperty, itemSourceBinding);

Updated

It is just an "important" note that might be useful as well for others in the future. I just did as the accepted answer did, it works, but the Visual Studio editor gave me a warning as follows

enter image description here

Is it a bug or a feature?

Upvotes: 0

Views: 1679

Answers (1)

Lucas Zhang
Lucas Zhang

Reputation: 18861

If you want to set BindingContext in xaml with parameters . You could check the following code .

<ContentPage.BindingContext>
    <local:DateTimeViewModel>
        <x:Arguments>
             <x:Double>1000</x:Double>
        </x:Arguments>
     </local:DateTimeViewModel>
</ContentPage.BindingContext>

It seems that you bind the binding context of ContentPage as a property of ViewModel . But it would be better to bind the whole ViewModel and then you could access its properties in anywhere of the page .

Upvotes: 2

Related Questions