Reputation: 63
I try to realize my first MVVM-Project. First I created model called "person.cs". Then I created a modelview "AddPerson.cs", which should dynamically creates the data, which is stored in person.cs. In my view (completely created with xaml) I have a button which should call a method "CreatePerson()" from my "AddPerson.cs". I like to bind the method.
Additionally I have created a label which should be bound to the class "person.cs" for example to the public string "Name".
How can I set the BindingContext of the Button to the "AddPerson.cs"-class and the BindingContext of the Label to the "person.cs"-class?
Upvotes: 1
Views: 1533
Reputation: 9990
You are missing some essential concepts which result in your requests being strange.
You don't data bind to the class definition, but to the instance of the class. As one ViewModel is a class it may contain instances of other classes that you data bind to, and everything except that is in 99% of cases a wrong thing to do and your example is not one of those 1% of cases.
So basically your ViewModel should be something like:
public class PersonViewModel
{
public Person Person {get; set}
public ICommand AddPersonCommand {get; set}
}
Your BindingContext is then an instance of PersonViewModel and then on Label you bind to Person while on the button you would bind to AddPersonCommand.
Upvotes: 1
Reputation: 14750
Yes this is possible.
Most of the Elements inherit BindablObject
. Each BindableObjaect
has a BindingContext
Property.
See: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/xaml/xaml-basics/data-binding-basics
MainViewModel
The Viewmodel for your entire page, that holds every sub-viewmodel.
public class MainViewModel
{
public AddPersonViewModel AddPersonViewModel { get; }
public PersonViewModel PersonViewModel { get; }
public MainViewModel()
{
// the passed action is just a fake action to simulate adding a person
AddPersonViewModel = new AddPersonViewModel(value => PersonViewModel.Name = value);
PersonViewModel = new PersonViewModel();
}
}
AddPersonViewModel
Contains your add logic.
public class AddPersonViewModel : INotifyPropertyChanged
{
public AddPersonViewModel(Action<string> onAction)
{
AddPerson = new Command(() =>
{
onAction(NewName); // call your update logic
NewName = ""; // reset name
});
}
public Command AddPerson { get; }
private string _name;
public string NewName
{
get => _name;
set
{
_name = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(NewName)));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
PersonViewModel
Contains your "new" Person.
public class PersonViewModel : INotifyPropertyChanged
{
private string _name;
public string Name
{
get => _name;
set
{
_name = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Name)));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
MainPage
Create and set your MainViewModel.
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
BindingContext = new MainViewModel();
}
}
MainPage.xaml
Here we bind the BindingContext
of Entry
and Button
to the AddPersonViewModel
property of our ContentPage's BindingContext
which is the MainViewModel
. And then we bind the Text
of the Label
and the Command
of the Button
to NewName
and AddPerson
properties of the local BindingContext
, which is AddPersonViewModel
Same for Label
.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:App5"
x:Class="App5.MainPage">
<StackLayout>
<Entry BindingContext="{Binding AddPersonViewModel}" Text="{Binding NewName}"
HorizontalOptions="FillAndExpand" />
<Button BindingContext="{Binding AddPersonViewModel}" Text="Click me!" Command="{Binding AddPerson}"
HorizontalOptions="Center" />
<Label Text="Added Person:" FontAttributes="Bold"
HorizontalOptions="Center"/>
<Label BindingContext="{Binding PersonViewModel}" Text="{Binding Name}"
HorizontalOptions="Center"/>
</StackLayout>
</ContentPage>
The example is very hacky, but I think you get the point. The key is the already mentioned property BindingContext
Upvotes: 1