Я разрабатываю приложение .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. поле. Однажды у меня сработало запланированное поведение, но потом я что-то изменил и не уверен, что я сделал по-другому.





Вы путаете свойства запроса и данные навигации на основе объектов. Свойства запроса могут быть только примитивными типами данных (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 и страницы сведений, но, может быть, это уже устарело?
Нет, вы либо используете свойства запроса, либо параметры навигации на основе объектов. Это не взаимозаменяемые вещи. Свойства запроса всегда передаются в форме URL, например: /SomePage?param1=value1¶m2=value2. Это невозможно со сложными типами данных, если они не передаются в виде строки JSON, что не происходит автоматически и от которого я бы не советовал из-за проблем с кодированием и удобочитаемости. Свойства запроса отлично подходят для простых вещей, таких как передача одного значения, но если вам нужно передать целые объекты, вам всегда понадобится словарный подход и IQueryAttributable.
@Julian Код MAUI рассказывает совершенно другую историю. Реальная история такова: URL-запрос анализируется в Dictionary<string,object> и используется для его применения к представлению и его BindingContext.
У вас опечатка в коде.
Конструктор QueryPropertyAttribute ожидает имя свойства и идентификатор внутри параметров запроса.
Итак, следуя вашему коду, вам нужно изменить nameof(TimeSeriesData) на nameof(Forecast).
namespace forecAstIng.ViewModel
{
[QueryProperty( name: nameof(Forecast), queryId: "Forecast")]
public partial class MorePageViewModel : BaseViewModel
{
public MorePageViewModel()
{
}
[ObservableProperty]
TimeSeriesData forecast;
}
}
Вы уверены, что экземпляр виртуальной машины, передаваемый в конструктор, действительно содержит те данные, которые, по вашему мнению, у него есть?