James Crutchley
James Crutchley

Reputation: 91

How do I get OnPropertyChanged to trigger on Orientation change by user?

I can get the device orientation and set a value for it in the constructor. It works as expected. But when user changes orientation of device OnChanged event does not trigger. I am probably wrong about how this all works. But I kind of expected the OnChanged event to trigger and update the displayed information when orientation changes?

TabletPodcastViewModel.cs

namespace NerdNewsNavigator2.ViewModel.Tablet;

public partial class TabletPodcastViewModel : ObservableObject
{
    #region Properties
    readonly TwitService _twitService;
    [ObservableProperty]
    int _orientation;
    public ObservableCollection<Podcast> Podcasts { get; set; } = new();
    #endregion
    public TabletPodcastViewModel(TwitService twit)
    {
        this._twitService = twit;
        _ = GetPodcasts();
        this._orientation = OnDeviceOrientationChange();
        System.Diagnostics.Debug.WriteLine("Device orientation is: " + Orientation);
        OnPropertyChanged(nameof(Orientation));
    }

    #region Get the Podcast and set the Podcast List
    async Task GetPodcasts()
    {
        var podcastList = await TwitService.GetListOfPodcasts();
        foreach (var item in podcastList)
        {
            var temp = await Task.FromResult(FeedService.GetFeed(item));
            Podcasts.Add(temp);
        }
    }
    #endregion
    public int OnDeviceOrientationChange()
    {
        if (DeviceDisplay.Current.MainDisplayInfo.Orientation == DisplayOrientation.Portrait) { return 2; }
        else return 3;
    }

    [RelayCommand]
    async Task Tap(string url)
    {
        var encodedUrl = HttpUtility.UrlEncode(url);
        await Shell.Current.GoToAsync($"{nameof(TabletShowPage)}?Url={encodedUrl}");
    }
}

Here is TAbletPodcastPage.xaml.cs

namespace NerdNewsNavigator2.View.Tablet;

public partial class TabletPodcastPage : ContentPage
{
   public TabletPodcastPage(TabletPodcastViewModel viewModel)
    {
        InitializeComponent();
        BindingContext = viewModel;
    }
}

Here is TabletPodcastPage.xaml:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:model="clr-namespace:NerdNewsNavigator2.Model"
             xmlns:viewmodel="clr-namespace:NerdNewsNavigator2.ViewModel.Tablet"
             x:Class="NerdNewsNavigator2.View.Tablet.TabletPodcastPage"
             x:DataType="viewmodel:TabletPodcastViewModel"
               Shell.NavBarIsVisible="True"
             Title="{Binding Orientation}">
    <Shell.BackButtonBehavior>
        <BackButtonBehavior IsEnabled="True" IsVisible="False"></BackButtonBehavior>
    </Shell.BackButtonBehavior>
    <CollectionView ItemsSource="{Binding Podcasts}" Margin="5" BackgroundColor="White" SelectionMode="None">
        <CollectionView.ItemsLayout>
            <GridItemsLayout Orientation="Vertical" Span="{Binding Orientation}"/>
        </CollectionView.ItemsLayout>
        <CollectionView.ItemTemplate>
            <DataTemplate x:DataType="model:Podcast">
                <Grid RowDefinitions="30,400,*" ColumnDefinitions="400">
                    <Grid.GestureRecognizers>
                        <TapGestureRecognizer 
                            Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:TabletPodcastViewModel}}, Path=TapCommand}"
                            CommandParameter="{Binding Url}"/>
                    </Grid.GestureRecognizers>
                    <Label  Grid.Row="0"
                        Text="{Binding Title}" 
                        TextColor="Black" 
                            HorizontalTextAlignment="Center"
                        FontSize="16" 
                            FontAttributes="Bold"
                        LineBreakMode="WordWrap"/>
                    <Image Grid.Row="1"
                    Aspect="AspectFit" 
                    MaximumHeightRequest="400" 
                    MaximumWidthRequest="400" 
                    Source="{Binding Image}">
                    </Image>
                    <Label Grid.Row="2"
                           Margin="5"
                           Text="{Binding Description}" 
                           FontSize="12" 
                           TextColor="Black" 
                           LineBreakMode="WordWrap"/>
                </Grid>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
</ContentPage>

Upvotes: 1

Views: 600

Answers (1)

James Crutchley
James Crutchley

Reputation: 91

After reading ToolkitmakerSteve's comment I went and found the doc for Orientation changes, I then figured out how to get it working!

Here is fixed TabletPodcastViewModel.cs:

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.


namespace NerdNewsNavigator2.ViewModel.Tablet;

public partial class TabletPodcastViewModel : ObservableObject
{
    #region Properties
    readonly TwitService _twitService;
    [ObservableProperty]
    int _orientation;
    private DisplayInfo MyMainDisplay { get; set; } = new();

    public ObservableCollection<Podcast> Podcasts { get; set; } = new();
    #endregion
    public TabletPodcastViewModel(TwitService twit)
    {
        this._twitService = twit;
        _ = GetPodcasts();
        DeviceDisplay.MainDisplayInfoChanged += DeviceDisplay_MainDisplayInfoChanged;
        this._orientation = OnDeviceOrientationChange();
      //  System.Diagnostics.Debug.WriteLine("Device orientation is: " + Orientation);
        OnPropertyChanged(nameof(Orientation));
    }

    #region Get the Podcast and set the Podcast List
    async Task GetPodcasts()
    {
        var podcastList = await TwitService.GetListOfPodcasts();
        foreach (var item in podcastList)
        {
            var temp = await Task.FromResult(FeedService.GetFeed(item));
            Podcasts.Add(temp);
        }
    }
    #endregion
    private void DeviceDisplay_MainDisplayInfoChanged(object? sender, DisplayInfoChangedEventArgs e)
    {
        MyMainDisplay = DeviceDisplay.Current.MainDisplayInfo;
        OnPropertyChanged(nameof(MyMainDisplay));
        Orientation = OnDeviceOrientationChange();
        OnPropertyChanged(nameof(Orientation));
        System.Diagnostics.Debug.WriteLine("Device orientation is: " + Orientation);
    }
    public int OnDeviceOrientationChange()
    {
        if (DeviceDisplay.Current.MainDisplayInfo.Orientation == DisplayOrientation.Portrait) { return 2; }
        else return 3;
    }

    [RelayCommand]
    async Task Tap(string url)
    {
        var encodedUrl = HttpUtility.UrlEncode(url);
        await Shell.Current.GoToAsync($"{nameof(TabletShowPage)}?Url={encodedUrl}");
    }
}

Here is TabletPodcastPage.xaml:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:model="clr-namespace:NerdNewsNavigator2.Model"
             xmlns:viewmodel="clr-namespace:NerdNewsNavigator2.ViewModel.Tablet"
             x:Class="NerdNewsNavigator2.View.Tablet.TabletPodcastPage"
             x:DataType="viewmodel:TabletPodcastViewModel"
               Shell.NavBarIsVisible="False"
             Title="">
    <Shell.BackButtonBehavior>
        <BackButtonBehavior IsEnabled="True" IsVisible="False"></BackButtonBehavior>
    </Shell.BackButtonBehavior>
    <CollectionView ItemsSource="{Binding Podcasts}" Margin="5" BackgroundColor="White" SelectionMode="None">
        <CollectionView.ItemsLayout>
            <GridItemsLayout Orientation="Vertical" Span="{Binding Orientation}"/>
        </CollectionView.ItemsLayout>
        <CollectionView.ItemTemplate>
            <DataTemplate x:DataType="model:Podcast">
                <Grid RowDefinitions="30,400,*" ColumnDefinitions="400">
                    <Grid.GestureRecognizers>
                        <TapGestureRecognizer 
                            Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:TabletPodcastViewModel}}, Path=TapCommand}"
                            CommandParameter="{Binding Url}"/>
                    </Grid.GestureRecognizers>
                    <Label  Grid.Row="0"
                        Text="{Binding Title}" 
                        TextColor="Black" 
                            HorizontalTextAlignment="Center"
                        FontSize="16" 
                            FontAttributes="Bold"
                        LineBreakMode="WordWrap"/>
                    <Image Grid.Row="1"
                    Aspect="AspectFit" 
                    MaximumHeightRequest="400" 
                    MaximumWidthRequest="400" 
                    Source="{Binding Image}">
                    </Image>
                    <Label Grid.Row="2"
                           Margin="5"
                           Text="{Binding Description}" 
                           FontSize="12" 
                           TextColor="Black" 
                           LineBreakMode="WordWrap"/>
                </Grid>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
</ContentPage>

This is working for detecting device orientation changes and applying numerical changes to span in GridItemsLayout! TY so much for the suggestion. I have been banging my head against a virtual wall trying to figure this out. I was at a loss as to how to go about figuring out what I needed to do.

Upvotes: 0

Related Questions