INotifyPropertyChanged not causing my View data to refresh

Dave C 21 Reputation points
2020-12-07T00:42:10.547+00:00

I'm new to Xamarin Forms. Been struggling with this all day now :(

My view doesn't refresh

My Object that I'm binding to...

using DTS_Driver.Classes;
using DTS_Driver.Models;
using System.Collections.ObjectModel;

namespace DTS_Driver.Classes_Static
{
    public static class Global_Objects
    {

        private static WebOrder _CurrentOrder = new WebOrder();
        public static WebOrder CurrentOrder
        {
            get
            {
                return _CurrentOrder;
            }
            set
            {
                _CurrentOrder = value;
            }
        }
}

My WebOrderClass (simplified by removing a ton of properties)

using System;
using System.ComponentModel;
using DTS_Driver.Classes_Static;
using DTS_Driver.Services;

namespace DTS_Driver.Classes
{

    public class WebOrder : ObservableObject
    {
        private string mLocationName; // 
        private string mPkid;


        public string LocationName
        {
            get
            {
                return mLocationName;
            }

            set
            {
                mLocationName = value;
                OnPropertyChanged("LocationName");
            }
        }

        public string Pkid
        {
            get
            {
                return mPkid;
            }

            set
            {
                mPkid = value;
                OnPropertyChanged("Pkid");
            }
        }

Inheriting this

using System.ComponentModel;

namespace DTS_Driver.Services
{
    public class ObservableObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string PropName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(PropName));
            }
        }
    }
}

changing a property like this...
Global_Objects.CurrentOrder.LocationName = "NEW NAME TEST"; DOES WORK

BUT... changing the object like this does not work (The original data stays in place with no sign of the new order details)
Global_Objects.CurrentOrder = (WebOrder)AnotherOrderThatIsNowCurrent

so i tried using this to set a new object to my current object, but nothing happens when i try it this way

public static void SetCurrentOrder (WebOrder WebOrd)
        {

            // Lets refresh a field so iNotifyPropertyChanged will do it's job and cause form to refresh
            string RememberPkid = Global_Objects.CurrentOrder.Pkid;
            Global_Objects.CurrentOrder = WebOrd;
            Global_Objects.CurrentOrder.Pkid = "BLAH";
            Global_Objects.CurrentOrder.Pkid = RememberPkid; // Stepping through this i see INotify events firing
        }

But the view doesn't seem to notice. My View XAML is as follows...

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:DTS_Driver.Classes_Static"
             x:Class="DTS_Driver.Views.CurrentOrderView">

    <ContentPage.Content>
        <StackLayout x:Name="MyStackLayout">
            <Label Text="Current Active Order"
                VerticalOptions="Start" 
                HorizontalOptions="CenterAndExpand" />

            <Frame BackgroundColor="WhiteSmoke" CornerRadius="10" Padding="0" HasShadow="True" Margin="0,0,0,0" VerticalOptions="Start" HorizontalOptions="FillAndExpand">

                <StackLayout BackgroundColor="WhiteSmoke" Margin="10,2,2,2">
                    <Label Text="{Binding LocationName}" Padding="-4" Margin="2,0,0,0" FontSize="16"/>
                    <Label Text="{Binding PickupDescription}" Padding="-1" Margin="2,0,0,0"  FontSize="11"/>
                    <Label Text="{Binding DeliveryLocation}" Padding="-2" Margin="2,0,0,0"  FontSize="10"/>
                    <Label Text="{Binding DeliveryDescription}" Padding="-1" Margin="2,0,0,0"  FontSize="11"/>

                    <Button Text="Mark as picked up" Padding="-1" Margin="2,0,0,0"  FontSize="11" x:Name="btnMarkAsPickedUp" Clicked="btnMarkAsPickedUp_Clicked"
                            IsEnabled="{Binding NotAtPickUpYet}" />

                    <Button Text="On the way (customer visible)" Padding="-1" Margin="2,0,0,0"  FontSize="11" x:Name="btnOnTheWay" Clicked="btnOnTheWay_Clicked"
                            IsEnabled="{Binding NotOnTheWayYet}"  />

                </StackLayout>
            </Frame>

        </StackLayout>
    </ContentPage.Content>
</ContentPage>

I am binding the data with this...

public partial class CurrentOrderView : ContentPage
    {

        public CurrentOrderView()
        {
            InitializeComponent();

            BindingContext = Global_Objects.CurrentOrder;
        }

I'm not going through a standard view model, as i need my data source to be available elsewhere in the application.

I'm a VB guy who's learning C# and Xamarin all at once, so that doesn't help things :(

Hoping someone can tell me what I'm doing wrong, without a complete re-write.

Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,319 questions
0 comments No comments
{count} votes

Accepted answer
  1. Leon Lu (Shanghai Wicresoft Co,.Ltd.) 71,441 Reputation points Microsoft Vendor
    2020-12-07T02:09:38.373+00:00

    Hello,​

    Welcome to our Microsoft Q&A platform!

    BUT... changing the object like this does not work (The original data stays in place with no sign of the new order details)
    Global_Objects.CurrentOrder = (WebOrder)AnotherOrderThatIsNowCurrent

    You cannot update the viewModel at the runtime, then make the view changed.
    If you want to change the view, you need to update the viewModel's property. Here is updated code(When you get the AnotherOrderThatIsNowCurrent object, then you can update the by following way, update the property one by one, do not set the object directly.)

       WebOrder AnotherOrderThatIsNowCurrent = new WebOrder() { LocationName = "TEstName12312412", Pkid = "12344444" };  
                   Global_Objects.CurrentOrder.LocationName = AnotherOrderThatIsNowCurrent.LocationName;  
                   Global_Objects.CurrentOrder.Pkid = AnotherOrderThatIsNowCurrent.Pkid;  
    

    I make a test with LocationName property, here is running GIF.

    45347-issue.gif

    Best Regards,

    Leon Lu


    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Dave C 21 Reputation points
    2020-12-07T09:31:40.513+00:00

    Thank you. My Class has 100 properties, so I was hoping I could shortcut it to keep the code short, but obviously I can't :(

    Much appreciated !

    0 comments No comments