Добавить несколько обязательных контекста в файл 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.

Другие вопросы по тегам