Добавить несколько обязательных контекста в файл xaml
Я пытаюсь реализовать свой первый MVVM-проект. Сначала я создал модель под названием "person.cs". Затем я создал представление модели "AddPerson.cs", которое должно динамически создавать данные, которые хранятся в person.cs. На мой взгляд (полностью создан с помощью xaml) у меня есть кнопка, которая должна вызывать метод "CreatePerson()" из моего "AddPerson.cs". Мне нравится связывать метод.
Кроме того, я создал метку, которая должна быть связана с классом "person.cs", например, с общедоступной строкой "Имя".
Как я могу установить BindingContext для кнопки в классе "AddPerson.cs" и BindingContext метки в классе "person.cs"?
2 ответа
Да, это возможно. Большинство элементов наследуют BindablObject
, каждый BindableObjaect
имеет BindingContext
Имущество. См.: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/xaml/xaml-basics/data-binding-basics
MainViewModel
Модель представления для всей вашей страницы, которая содержит каждую подмодель модели.
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
Содержит вашу логику добавления.
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
Содержит ваш "новый" человек.
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;
}
Главная страница
Создайте и настройте свою MainViewModel.
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
BindingContext = new MainViewModel();
}
}
MainPage.xaml
Здесь мы связываем BindingContext
из Entry
а также Button
к AddPersonViewModel
собственность нашего ContentPage's BindingContext
какой MainViewModel
, И тогда мы связываем Text
из Label
и Command
из Button
в NewName
а также AddPerson
свойства местного BindingContext
, который AddPersonViewModel
То же самое для 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>
Пример очень хакерский, но я думаю, вы поняли. Ключ уже упоминавшегося свойства BindingContext
Вы упускаете некоторые важные понятия, из-за которых ваши запросы выглядят странно.
Вы привязываете данные не к определению класса, а к экземпляру класса. Поскольку один ViewModel является классом, он может содержать экземпляры других классов, к которым привязаны ваши данные, и все, кроме того, что в 99% случаев является неправильным действием, и ваш пример не является одним из этих 1% случаев.
В общем, ваша ViewModel должна выглядеть примерно так:
public class PersonViewModel
{
public Person Person {get; set}
public ICommand AddPersonCommand {get; set}
}
Тогда ваш BindingContext является экземпляром PersonViewModel, а затем на ярлыке вы связываетесь с Person, а на кнопке вы привязываете к AddPersonCommand.