Home > front end >  INotifyPropertyChanged in wpf application of List
INotifyPropertyChanged in wpf application of List

Time:10-03

Problem
I want to refresh my wpf view when a change is made in a List of objects in my application, but it wont register the INotifyChanged method when I change a value.

What I've tried
I went to multiple different stackoverflow pages with sort of the same problem but I don't get it working right. It wont register a change in a object in the list.

my code

below is the code for the MainWindow of the WPF application in wher with the last button click I change the value of XLocation in an object out of a list.

public partial class MainWindow : Window
{
    private string filePathArtist { get; set; }
    private string filePathGrid { get; set; }
    public Game.Game  Game { get; set; }
    public MainWindow()
    {
        InitializeComponent();
        filePathGrid = String.Empty;
        filePathArtist = String.Empty;
    }

    private void BtnOpen_Click(object sender, RoutedEventArgs e)
    {
        OpenFileDialog openFileDialog = new OpenFileDialog();

        bool? res = openFileDialog.ShowDialog();
        if (res == true)
        {
            string filepathgrid = openFileDialog.FileName;
            filePathGrid = filepathgrid;
            GridTextBox.Text = filepathgrid;

        }

       
    }

    private void PickArtistBtn_Click(object sender, RoutedEventArgs e)
    {
        OpenFileDialog openFileDialog = new OpenFileDialog();

        bool? res = openFileDialog.ShowDialog();
        if (res == true)
        {
            string filepathartist = openFileDialog.FileName;
            filePathArtist = filepathartist;
            ArtistTextBox.Text = filepathartist;

        }

    }

    private void CreateGridBtn_Click(object sender, RoutedEventArgs e)
    {
        Game = new Game.Game(filePathGrid, filePathArtist);
        this.DataContext = Game;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Game.Artists[0].XLocation = 30;
    }
}

Next code is the Game class where is implemented a INotfyPropertyChanged on the list of Artists.

public class Game : INotifyPropertyChanged
{
    public List<Artist> _artists;

    public List<Artist> Artists
    {
        get
        {
            return _artists;
        }
        set
        {
            _artists = value;
            OnPropertyChanged("Artists");
        }
    }

    public List<ITile> Tiles { get; set; }

    public Game()
    {

    }
    public Game(string graphPath, string artistPath)
    {
        IDataParser graphParser = DataFactory.DataFactory.Instance.CreateParser(graphPath);
        IDataParser artistParser = DataFactory.DataFactory.Instance.CreateParser(artistPath);
        Tiles = graphParser.ParseGridData(graphPath);
        Artists = artistParser.ParseArtistData(artistPath);
        Test = "new Game";
    }

    public string Test { get; set; } = "t";

    public event PropertyChangedEventHandler? PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Ive also added the INotifyPropertyChanged in the Artists class

public class Artist : INotifyPropertyChanged
{
    private float _xLocation;
    private float _yLocation;
    private int _xVelocity;
    private int _yVelocity;
    public float XLocation
    {
        get => _xLocation;
        set
        {
            _xLocation = value;
            OnPropertyChanged("XLocation");
        }
    }
    public float ConvertedXLoc
    {
        get => XLocation * (float)3.75;
        set { }
    }

    public float YLocation
    {
        get => _yLocation;
        set
        {
            _yLocation = value;
            OnPropertyChanged("YLocation");
           
        }
    }

    public float ConvertedYLoc
    {
        get => YLocation * (float)3.75;
        set { }
    }

    public int XVelocity
    {
        get => _xVelocity;
        set
        {
            _xVelocity = value;
        }
    }

    public int YVelocity
    {
        get => _yVelocity;
        set
        {
            _yVelocity = value;
        }
    }


    public event PropertyChangedEventHandler? PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Then here is the Xaml code where I bind the objects to the wpf UI.

<Window x:Class="BroadwayBoogie.MainWindow"
    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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:game="clr-namespace:BroadwayBoogie.Game"
    mc:Ignorable="d"
    Title="MainWindow" Height="900" Width="900"
    >
<Window.DataContext>
    <game:Game/>
</Window.DataContext>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="201*"/>
        <ColumnDefinition Width="199*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="21*"/>
        <RowDefinition Height="401*"/>
        <RowDefinition Height="20*"/>
    </Grid.RowDefinitions>
    <Button x:Name="BtnOpen" Content="Pick Grid" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Click="BtnOpen_Click"/>
    <TextBox x:Name="GridTextBox" HorizontalAlignment="Center" TextWrapping="NoWrap" VerticalAlignment="Center" Width="266" />
    <Button x:Name="PickArtistBtn" Content="Pick Artist" HorizontalAlignment="Left" Margin="356,0,0,0" VerticalAlignment="Center" Click="PickArtistBtn_Click" RenderTransformOrigin="-0.135,0.647"/>
    <TextBox x:Name="ArtistTextBox" HorizontalAlignment="Left" Margin="30,14,0,0" TextWrapping="NoWrap" VerticalAlignment="Top" Width="231" Grid.Column="1"/>
    <Button x:Name="CreateGridBtn" Grid.Column="1" Content="Create Grid" HorizontalAlignment="Left" Margin="311,14,0,0" VerticalAlignment="Top" Click="CreateGridBtn_Click"/>

    <Canvas Width="800" Height="800" Grid.ColumnSpan="2" Margin="49,15,51,27" Grid.Row="1" Background="DarkSeaGreen" Grid.RowSpan="2">
        <ItemsControl Name="tilesItemsControl" ItemsSource="{Binding Tiles}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Canvas>
                        <Rectangle
                        Width="15"
                        Height="15"
                        Fill="{Binding Color}"
                        Canvas.Left ="{Binding ConvertedXLoc}"
                        Canvas.Top="{Binding ConvertedYLoc}" />
                    </Canvas>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
        <ItemsControl Name="ArtistItemsControl" ItemsSource="{Binding Artists}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Canvas>
                        <Rectangle
                            Width="3.75"
                            Height="3.75"
                            Fill="Black"
                            Canvas.Left ="{Binding ConvertedXLoc}"
                            Canvas.Top="{Binding ConvertedYLoc}" />
                    </Canvas>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Canvas>
    <Grid/>
    <Button Content="Button" HorizontalAlignment="Left" Margin="4,0,0,0" Grid.Row="2" VerticalAlignment="Center" Click="Button_Click"/>



</Grid>

So with the press of the button I added for testing purposes. It changes a value in the List and then the PropertyChanged method should detect that but it doesn't detect it it just skips it.

Question
So my basic question is, how do I detect the change of a property from objects out of the List of Artists.

CodePudding user response:

OnPropertyChanged will only be executed when the property itself is changed. A new item in a list is not a property change. That's the reason why no updates happens.

Instead a List, try an ObservableCollection. An ObservableCollection implements an additional INotifyCollectionChanged which makes the UI able to react on changing items in the list.

  • Related