Привязка XAML в качестве аргументов

#c# #xaml #data-binding #maui

Вопрос:

Я пытаюсь передать модель представления в качестве аргумента страницы из XAML.

Вот базовая страница:

 public abstract class BaseContentPage<T> : ContentPage where T : BaseVm
{
    public BaseContentPage(T viewModel, string pageTitle)
    {
        BindingContext = ViewModel = viewModel;
        Title = pageTitle;
    }

    protected T ViewModel { get; }
}

public abstract class BaseTabbedPage<T> : TabbedPage where T : BaseVm
{
    public BaseTabbedPage(T viewModel, string pageTitle)
    {
        BindingContext = ViewModel = viewModel;
        Title = pageTitle;
    }

    protected T ViewModel { get; }
}
 

Параметр содержит список устройств, определенных таким образом:

 public partial class SettingsPage : BaseTabbedPage<SettingsVm>
{
    public SettingsPage(SettingsVm vm) : base(vm, "Settings")
    {
        InitializeComponent();
    }
}

public class SettingsVm : BaseVm
{
    public DeviceListVm Devices { get; set; }

    public SettingsVm(ILogger<SettingsVm> logger, MyConfig config) { }
}

public partial class DeviceListPage : BaseContentPage<DeviceListVm>
{
    public DeviceListPage(DeviceListVm vm) : base(vm, "Devices")
    {
        InitializeComponent();
    }
    public DeviceListPage() : base(null, "Devices")
    {
        InitializeComponent();
    }
}
 

Тогда самое сложное-это XAML:

 <p:BaseTabbedPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
    xmlns:p="clr-namespace:MyProject.Pages"
    xmlns:vm="clr-namespace:MyProject.ViewModels"
    xmlns:vmd="clr-namespace:MyProject.ViewModels.Devices"
    xmlns:local="clr-namespace:MyProject"
    x:Class="MyProject.Pages.SettingsPage"
    x:TypeArguments="vm:SettingsVm">
    <NavigationPage Title="Schedule" IconImageSource="schedule.png">
        <x:Arguments>
            <p:DeviceListPage ViewModel="{Binding Devices}">
                <!--x:Arguments>
                    <vmd:DeviceListVm>{Binding Devices}</vmd:DeviceListVm>
                </x:Arguments-->
            </p:DeviceListPage>
        </x:Arguments>
    </NavigationPage>

</p:BaseTabbedPage>
 

Мне не удается передавать устройства в качестве аргумента страницы списка устройств.

Я не хочу делать это программно, так как представления моделей предназначены для внедрения, за исключением этого случая, когда модель корневого представления содержит модель подвида для использования дочерней страницей.

Если я использую свойство ViewModel, я получаю следующую ошибку:

Ошибка XFC0009: Для «ViewModel» не найдено свойство, свойство привязки или событие или тип несоответствия между значением и свойством.

РЕДАКТИРОВАТЬ Я изменил базовый класс, чтобы объявить BindableProperty :

 public abstract class BaseContentPage<T> : ContentPage where T : BaseVm
{
    public BaseContentPage(T viewModel, string pageTitle)
    {
        ViewModel = viewModel;
        Title = pageTitle;
    }

    public T ViewModel
    {
        get => (T)GetValue(ViewModelProperty);
        set => SetValue(ViewModelProperty, BindingContext = value);
    }
    public BindableProperty ViewModelProperty = BindableProperty.Create(nameof(ViewModel), typeof(T), typeof(BaseContentPage<T>));
}

public abstract class BaseTabbedPage<T> : TabbedPage where T : BaseVm
{
    public BaseTabbedPage(T viewModel, string pageTitle)
    {
        ViewModel = viewModel;
        Title = pageTitle;
    }

    public T ViewModel
    {
        get => (T)GetValue(ViewModelProperty);
        set => SetValue(ViewModelProperty, BindingContext = value);
    }
    public BindableProperty ViewModelProperty = BindableProperty.Create(nameof(ViewModel), typeof(T), typeof(BaseTabbedPage<T>));
}
 

Затем я все равно получаю ту же ошибку XFC0009.

Комментарии:

1. Какой тип страницы списка устройств? Кажется, у вас Protected T Viewmodel есть, но если вы хотите использовать его так, как вы это делаете, вам следует сделать BindableProperty

2. @JuanSturla Привязка свойства применяет значение к экземпляру по умолчанию. Можно ли передать привязку в качестве аргумента конструктора?

3. Является ли передача аргументов в XAML тем, о чем вы говорите?

4. @JessieZhang-MSFT <p:DeviceListPage> вызывает конструктор по умолчанию DeviceListPage() . Я бы хотел, чтобы он вызывал конструктор с моделью представления DeviceListPage(DeviceListVm vm)

5. @JessieZhang-MSFT Не нашел синтаксис для использования с привязкой