Невозможно получить доступ к наблюдаемому свойству в модели представления из соответствующего файла .xaml представления — .NET MAUI MVVM

Я разрабатываю приложение .NET MAUI, в котором использую шаблон MVVM через пакет nuget Community.Toolkit.MVVM. В приведенном ниже коде на MorePage я пытаюсь связать заголовок с Forecast.Name, который является наблюдаемым свойством MorePageViewModel, которое установлено в качестве контекста привязки для самого MorePage. Я проверил, что функция навигации выполняется с передачей нужного объекта, поэтому проблема, похоже, либо в MorePageViewModel, либо в MorePage.xaml(.cs), но я не уверен, где именно.

namespace forecAstIng.Model
{
    public abstract class TimeSeriesData
    {
        public string Name { get; set; }
        public char MeasurementUnit { get; set; }

        public double HourTimeInterval { get; set; } = 24;
        public double DayTimeInterval => HourTimeInterval / 24;
        public double MinuteTimeInterval => HourTimeInterval * 60;

        public List<double> ValueHistory { get; set; }
        public List<double> ValuePredictions { get; set; }

        public double HistoryHigh { get; set; }
        public double HistoryLow { get; set; }

        public string CurrentBehaviour { get; set; }
        public double CurrentValue { get; set; }
    }

    class WeatherData : TimeSeriesData
    {
    }

    class StockData : TimeSeriesData
    {
    }
}
using forecAstIng.View;

namespace forecAstIng.ViewModel
{
    public partial class ForecastsViewModel : BaseViewModel
    {
        public ObservableCollection<TimeSeriesData> Forecasts { get; } = new();

        public ForecastsViewModel()
        {
            Title = "forecAstIng";
            Forecasts.Add(new WeatherData { Name = "Prague, CZ", CurrentBehaviour = "sunny", CurrentValue = 23.8776575, HistoryHigh = 27.389, HistoryLow = 20, MeasurementUnit = 'C' });
        }

        [RelayCommand]
        async Task GoToMorePage(TimeSeriesData forecast)
        {
            if (forecast is null)
                return;

            await Shell.Current.GoToAsync(nameof(MorePage), true, new Dictionary<string, object>
                {
                    {"Forecast", forecast}
                });
        }
    }
}
namespace forecAstIng.ViewModel
{
    [QueryProperty(nameof(TimeSeriesData), "Forecast")]
    public partial class MorePageViewModel : BaseViewModel
    {
        public MorePageViewModel()
        {
        }

        [ObservableProperty]
        TimeSeriesData forecast;
    } 
}
<?xml version = "1.0" encoding = "utf-8" ?>
<ContentPage x:Class = "forecAstIng.View.MorePage"
             xmlns = "http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x = "http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:model = "clr-namespace:forecAstIng.Model"
             xmlns:viewmodel = "clr-namespace:forecAstIng.ViewModel"
             x:DataType = "viewmodel:MorePageViewModel"
             Title = "{Binding Forecast.Name}"
             BackgroundColor = "#402E7A">

</ContentPage>
namespace forecAstIng.View
{
    public partial class MorePage : ContentPage
    {
        public MorePage(MorePageViewModel vm)
        {
            InitializeComponent();
            BindingContext = vm;
        }
    }
}

Маршрут регистрируется в AppShell, а временные службы добавляются в MauiProgram.cs.

Заголовок на MorePage просто пуст.

Безуспешно я попытался изменить имя свойства, доступность, имя «Прогноз», которое используется повсюду в качестве имени свойства в файле MorePage.xaml и функции навигации, а также имя автоматически созданной поддержки пакета nuget. поле. Однажды у меня сработало запланированное поведение, но потом я что-то изменил и не уверен, что я сделал по-другому.

Вы уверены, что экземпляр виртуальной машины, передаваемый в конструктор, действительно содержит те данные, которые, по вашему мнению, у него есть?

Jason 31.07.2024 20:02
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
51
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы путаете свойства запроса и данные навигации на основе объектов. Свойства запроса могут быть только примитивными типами данных (int, bool, ...) и string.

Теперь вы передаете свой аргумент Forecast через объектно-ориентированную навигацию, выполнив следующие действия:

await Shell.Current.GoToAsync(nameof(MorePage), true, new Dictionary<string, object>
{
    {"Forecast", forecast}
});

На самом деле это передает Dictionary<string, object> в ViewModel и требует от вас реализации метода получения для обработки навигационных данных, точнее, ваша ViewModel должна реализовать интерфейс IQueryAttributable:

namespace forecAstIng.ViewModel
{
    public partial class MorePageViewModel : IQueryAttributable, BaseViewModel
    {
        [ObservableProperty]
        TimeSeriesData forecast;
    }

    public void ApplyQueryAttributes(IDictionary<string, object> query)
    {
        Forecast = query["Forecast"] as TimeSeriesData;
    }
}

Примечание: [QueryProperty(nameof(TimeSeriesData), "Forecast")] в любом случае не будет работать для свойств запроса, потому что так и должно быть [QueryProperty(nameof(Forecast), "Forecast")]. Одним из аргументов атрибута QueryProperty является имя свойства, а другим — имя параметра запроса. Вы передали имя типа, а не свойства. Однако это не решит вашу проблему, я просто упоминаю об этом для полноты картины.

Спасибо за ответ! Я все еще новичок как в MAUI, так и в MVVM в целом, и я думал, что это будет работать автоматически благодаря пакету mvvm из набора инструментов сообщества. Я также очень внимательно слежу за семинаром Джеймса Монтеманьо MAUI, и, как я понял, он также имел его для своего класса Monkey и страницы сведений, но, может быть, это уже устарело?

Reptiliand 01.08.2024 11:37

Нет, вы либо используете свойства запроса, либо параметры навигации на основе объектов. Это не взаимозаменяемые вещи. Свойства запроса всегда передаются в форме URL, например: /SomePage?param1=value1&param2=value2. Это невозможно со сложными типами данных, если они не передаются в виде строки JSON, что не происходит автоматически и от которого я бы не советовал из-за проблем с кодированием и удобочитаемости. Свойства запроса отлично подходят для простых вещей, таких как передача одного значения, но если вам нужно передать целые объекты, вам всегда понадобится словарный подход и IQueryAttributable.

Julian 01.08.2024 12:00

@Julian Код MAUI рассказывает совершенно другую историю. Реальная история такова: URL-запрос анализируется в Dictionary<string,object> и используется для его применения к представлению и его BindingContext.

Sir Rufo 01.08.2024 21:15

У вас опечатка в коде.

Конструктор QueryPropertyAttribute ожидает имя свойства и идентификатор внутри параметров запроса.

Итак, следуя вашему коду, вам нужно изменить nameof(TimeSeriesData) на nameof(Forecast).

namespace forecAstIng.ViewModel
{
    [QueryProperty( name: nameof(Forecast), queryId: "Forecast")]
    public partial class MorePageViewModel : BaseViewModel
    {
        public MorePageViewModel()
        {
        }

        [ObservableProperty]
        TimeSeriesData forecast;
    } 
}

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

Похожие вопросы

Устойчивые функции Azure не вызываются при использовании с триггером Q с использованием управляемого удостоверения
Как я могу преобразовать этот SQL-запрос в linq, когда у меня есть подзапрос, группировка и предложение?
Проблема развертывания Blazor WASM Core в Azure
Преобразование оператора foreach в оператор выбора
Что происходит, когда несколько задач C# запускаются после завершения другой задачи?
ASP .NET Core — расширение @Html.EditorFor для добавления <span>
Netwonsoft JsonConvert.Deserialization выдает исключение JsonSerializationException: «Ошибка преобразования значения «Имя моего пользовательского объекта» в тип «System.Type»
Как обеспечить автоматическое масштабирование для CollectionView в объекте Popup из CommunityToolkit.Maui после его заполнения с помощью события нажатия кнопки на платформе Windows?
Перенаправление вызова .NET Core OIDC не работает с интерфейсом Angular
Как добавить несколько веб-приложений Blazor в существующий веб-API