102425074
102425074

Reputation: 811

Why I can't update the UI when binding a class inherits the interface?

I am trying to write a demo of binding a class inherits the interface.

Here is the code of interface:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace App1
{
    public interface BaseClass
    {
        string AAA { get; set; }
    }
}

Here is code-behind of the Page:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409

namespace App1
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page, INotifyPropertyChanged
    {
        public BaseClass BC;
        public static MainPage MP;
        public MainPage()
        {
            this.InitializeComponent();
            MP = this;
            BC = new ChildClass();
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void RaisePropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
        public class ChildClass : BaseClass
        {
            string _AAA = "123";
            public string AAA
            {
                get { return _AAA; }
                set { _AAA = value; MP.RaisePropertyChanged("AAA"); }
            }

        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            BC.AAA = "456";
        }
    }
}

And finally here is the XAML:

<Page
    x:Class="App1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <TextBlock Text="{x:Bind BC.AAA,Mode=OneWay}"></TextBlock>
        <Button Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Click="Button_Click">123</Button>
    </Grid>
</Page>

After I ran the program, it will display the default string of AAA successfully. However, when I clicked the button, it can't change the text to "456".

I wonder if there is the INotifyPropertyChanged problem. But I don't know what's wrong with it.

Would you please tell me what's wrong with this? Thank you.

Upvotes: 0

Views: 119

Answers (1)

Muzib
Muzib

Reputation: 2581

2 mistakes:

First:

Notice that the ChidClass calls to MP.RaisePropertyChanged("AAA"), not the BaseClass. So, instead of declaring BC like

public BaseClass BC;

do

public ChildClass BC; instead.

Second: the property AAA doesn't belong to MainPage class, it belongs to ChildClass, so instead of implementing INotifyPropertyChanged in the MainPage, implement it in the ChildClass:

public class ChildClass : BaseClass, INotifyPropertyChanged
{
    string _AAA = "123";
    public string AAA
    {
        get { return _AAA; }
        set { _AAA = value; RaisePropertyChanged("AAA"); }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    protected void RaisePropertyChanged(string name)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

This should work.

Edit: The first mistake you made, if it was on intention, because you want to bind the UIs to this interface, then Sorry, you can't do that.

Why? because, to achieve that, you need to raise INotifyPropertyChanged event in that interface, but interfaces in c# (currently c# 7.3) doesn't let you do any default implementation, which means you can't write any code to raise that event. Having said that, C# 8.0, which is coming in near future, will have this capability. Can you wait till then?

Upvotes: 1

Related Questions