У меня есть простое приложение с фреймом в MainPage.xaml, который переключается между MediaCenterPage.xaml и PlayerPage.xaml. Теперь я хочу, чтобы выбранный фильм в MediaCenter был доступен на PlayerPage. Если я использую привязку и ссылаюсь на модель, это, конечно, два разных экземпляра объекта. Каков правильный подход к обмену данными между страницами?
MainPage.xaml
<Page
x:Class = "WinUI3Demo.Pages.MediaCenter.MainPage"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:local = "using:WinUI3Demo.Pages.MediaCenter"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
Background = "{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable = "d" />
MainPage.xaml.cs
namespace WinUI3Demo.Pages.MediaCenter
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public static Frame MainFrame = new();
public MainPage()
{
this.InitializeComponent();
MainFrame.Navigate(typeof(MediaCenterPage));
this.Content = MainFrame;
}
}
}
Медиацентрпаже.xaml
<?xml version = "1.0" encoding = "utf-8" ?>
<Page
x:Class = "WinUI3Demo.Pages.MediaCenter.MediaCenterPage"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:local = "using:WinUI3Demo.Pages"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:models = "using:WinUI3Demo.ViewModels"
Background = "{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable = "d">
<Page.DataContext>
<models:MediaModel x:Name = "Model" />
</Page.DataContext>
<Grid Padding = "16">
<Grid.RowDefinitions>
<RowDefinition Height = "*" />
<RowDefinition Height = "Auto" />
</Grid.RowDefinitions>
<Grid Grid.Row = "0">
<Grid.RowDefinitions>
<RowDefinition Height = "10*" />
<RowDefinition Height = "1*" />
<RowDefinition Height = "1*" />
</Grid.RowDefinitions>
<Viewbox Grid.Row = "1" HorizontalAlignment = "Left">
<TextBlock x:Name = "HeaderTextBlock" FontWeight = "ExtraBold" />
</Viewbox>
<Viewbox
Grid.Row = "0"
Margin = "0,15,0,0"
HorizontalAlignment = "Center"
VerticalAlignment = "Center"
Stretch = "UniformToFill">
<MediaPlayerElement
x:Name = "MediaPlayer"
AreTransportControlsEnabled = "False"
AutoPlay = "True"
Source = "{x:Bind models:Selected, Mode=OneWay}" />
</Viewbox>
<Viewbox Grid.Row = "2" HorizontalAlignment = "Left">
<TextBlock
x:Name = "ContentTextBlock"
Width = "880"
TextWrapping = "WrapWholeWords" />
</Viewbox>
</Grid>
<ScrollView
Grid.Row = "1"
Height = "250"
Padding = "0,10,0,0"
ContentOrientation = "Horizontal">
<ItemsView
x:Name = "MediaCenterItemView"
ItemsSource = "{x:Bind Model.Objects, Mode=OneWay}"
PointerPressed = "MediaCenterItemView_PointerPressed"
SelectionChanged = "ItemsView_SelectionChanged">
<ItemsView.Layout>
<LinedFlowLayout
ItemsStretch = "Fill"
LineHeight = "250"
MinItemSpacing = "15" />
</ItemsView.Layout>
<ItemsView.ItemTemplate>
<DataTemplate x:DataType = "models:MediaObject">
<ItemContainer>
<Grid>
<Image Source = "{x:Bind Thumbnail, Mode=OneWay}" Stretch = "Uniform" />
</Grid>
</ItemContainer>
</DataTemplate>
</ItemsView.ItemTemplate>
</ItemsView>
</ScrollView>
</Grid>
</Page>
Медиацентрпаже.xaml.cs
namespace WinUI3Demo.Pages.MediaCenter
{
public sealed partial class MediaCenterPage : Page
{
public static MediaObject SelectedMovie;
public MediaCenterPage()
{
this.InitializeComponent();
}
private void ItemsView_SelectionChanged(ItemsView sender, ItemsViewSelectionChangedEventArgs args)
{
if (MediaCenterItemView.SelectedItem != null)
{
var selectedMovie = MediaCenterItemView.SelectedItem as MediaObject;
HeaderTextBlock.Text = selectedMovie.Title;
ContentTextBlock.Text = selectedMovie.Description;
}
}
private void MediaCenterItemView_PointerPressed(object sender, PointerRoutedEventArgs e)
{
if (MediaCenterItemView.SelectedItem != null)
{
Frame.Navigate(typeof(PlayerPage));
}
}
}
}
PlayerPage.xaml
<?xml version = "1.0" encoding = "utf-8" ?>
<Page
x:Class = "WinUI3Demo.Pages.MediaCenter.PlayerPage"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:local = "using:WinUI3Demo.Pages"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:models = "using:WinUI3Demo.ViewModels"
Background = "{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable = "d">
<Page.DataContext>
<models:MediaModel x:Name = "Model" />
</Page.DataContext>
<Grid>
<StackPanel>
<AppBarButton Click = "BackButton_Click" Label = "Back" />
<Grid>
<MediaPlayerElement
x:Name = "MediaPlayer"
AreTransportControlsEnabled = "True"
AutoPlay = "True"
Source = "{x:Bind , Mode=OneWay}" />
</Grid>
</StackPanel>
</Grid>
</Page>
PlayerPage.xaml.cs
namespace WinUI3Demo.Pages.MediaCenter
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class PlayerPage : Page
{
public PlayerPage()
{
this.InitializeComponent();
}
private void BackButton_Click(object sender, RoutedEventArgs e)
{
MainPage.MainFrame.Navigate(typeof(MediaCenterPage));
}
}
}
ViewModel//MediaModel.cs
namespace WinUI3Demo.ViewModels
{
public class MediaModel : ObservableObject
{
private ObservableCollection<MediaObject> _objects;
public ObservableCollection<MediaObject> Objects
{
get => _objects;
set => SetProperty(ref _objects, value);
}
private MediaObject _selectedMovie;
public MediaObject SelectedMovie
{
get => _selectedMovie;
set => SetProperty(ref _selectedMovie, value);
}
public MediaModel()
{
Objects = new();
}
public void AddObject(MediaObject mediaObject)
{
Objects.Add(new MediaObject(mediaObject.Filename, mediaObject.Thumbnail, mediaObject.Title, mediaObject.Description, mediaObject.Trailer) { Id = Guid.NewGuid() });
}
}
public class MediaObject : ObservableObject
{
public Guid Id { get; set; }
public string Title { get; set; }
public string Filename { get; set; }
public string Description { get; set; }
public BitmapImage Thumbnail { get; set; }
public MediaSource Trailer { get; set; }
public MediaSource Movie { get; set; }
public MediaObject(string _filename, BitmapImage _thumbnail, string _title, string _description, MediaSource _trailer)
{
Filename = _filename;
Thumbnail = _thumbnail;
Title = _title;
Description = _description;
Trailer = _trailer;
Movie = _trailer;
}
}
}
Спасибо за ваше руководство @YangXiaoPo-MSFT. Это сработало отлично. Могу я спросить, как лучше всего было бы поделиться наблюдаемым свойством, указывающим, что представляет собой выбранный фильм? Можно ли иметь это в модели? Обновил мой вопрос, чтобы вы могли увидеть его в MediaModel.cs. Это правильный подход MVVM? Посмотрите SelectedMovie.
Например, вы можете сделать свой MainPage
MediaModel
MyMediaModel
. Затем Frame.Navigate(TypeName, MyMediaModel)
и установите DataContext
в Page.OnNavigatedTo
из MediaCenterPage
и PlayerPage
.
Код
public sealed partial class BlankPage1 : Page
{
protected override void OnNavigatedTo(NavigationEventArgs e)
{
MediaModel m = (MediaModel)e.Parameter;
DataContext = m;
}
}
КСАМЛ "{x:Bind ((local:MediaModel)DataContext).SelectedMovie}"
Но в зависимости от вашего контекста вы можете передать только SelectedMovie
или достаточно статической переменной.
См. Frame.Navigate(TypeName, Object) и Page.OnNavigatedTo(NavigationEventArgs) . Также проверьте stackoverflow.com/questions/78291201/…