ObservableCollection doesn't update listView

Imilio 41 Reputation points
2022-01-24T08:55:57.94+00:00

I want to update a listview in UserControl included in MainWindow when adding/removing/Editing an entry over opening a Window.
When clicking the save button (in code behind the method "SaveUsers" is called from the class "UserTask"), nothing happens.
Can anyone please help me to see, what I'm doing wrong?

Best regards
Imilio

What I have done:

XAML MainWindow

<Window x:Class="WPF_App.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:local="clr-namespace:WPF_App"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid x:Name="MainGrid">

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="70"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <StackPanel Grid.Column="0" Orientation="Vertical" VerticalAlignment="Top" >
            <Button Height="50" Width="50" Content="User" Margin="10" Click="User_Click"  />
            <Button Height="50" Width="50" Content="Pub" Margin="10"/>
        </StackPanel>

    </Grid>
</Window>

C# MainWindow

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WPF_App.Usercontrol;

namespace WPF_App
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void User_Click(object sender, RoutedEventArgs e)
        {
            UserControl1 oUser = new UserControl1();
            Grid.SetColumn(oUser, 1);
            MainGrid.Children.Add(oUser);
        }
    }
}

XAML UserControl

<UserControl x:Class="WPF_App.Usercontrol.UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WPF_App.Usercontrol" xmlns:local1="clr-namespace:WPF_App.Classes"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800" Background="White">

    <UserControl.DataContext>
        <local1:UserTask/>
    </UserControl.DataContext>

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <ListView Grid.Column="0" ItemsSource="{Binding ListOfUser}">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Firstname" x:Name="Firstname" Width="200">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Firstname}" TextWrapping="Wrap"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="Lastname" x:Name="Lastname" Width="200">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Lastname}" TextWrapping="Wrap"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                </GridView>
            </ListView.View>
        </ListView>

        <StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Top" Margin="20,0,0,0">

            <Button Height="25" Width="50" Content="Add" Margin="10" Click="Add_Click"  />
            <Button Height="25" Width="50" Content="Edit" Margin="10" />
            <Button Height="25" Width="50" Content="Delete" Margin="10"/>

        </StackPanel>

    </Grid>
</UserControl>

C# UserControl

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WPF_App.Classes;
using WPF_App.ucWindow;

namespace WPF_App.Usercontrol
{
    /// <summary>
    /// Interaktionslogik für UserControl1.xaml
    /// </summary>
    public partial class UserControl1 : UserControl
    {
        UserTask userDC = new UserTask();
        public UserControl1()
        {
            InitializeComponent();
            this.DataContext = userDC;
        }

        private void Add_Click(object sender, RoutedEventArgs e)
        {
            Window1 oAdd = new Window1();
            oAdd.DataContext = this;
            oAdd.Owner = Application.Current.MainWindow;
            oAdd.ShowDialog();

        }
    }
}

XAML Window1

<Window x:Class="WPF_App.ucWindow.Window1"
        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:local="clr-namespace:WPF_App.ucWindow" 
        mc:Ignorable="d"
        Title="Window1" Height="450" Width="400">

    <Grid>

        <StackPanel>

            <StackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="0,0,0,10">
                <Label Content="Firstname:" Width="120" />
                <TextBox x:Name="tbFirstname" Height="25" Width="230" Margin="0,0,5,0" Text="{Binding NewUser.Firstname}"/>
            </StackPanel>

            <StackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="0,0,0,10">
                <Label Content="Firstname:" Width="120" />
                <TextBox x:Name="tbLastname" Height="25" Width="230" Margin="0,0,5,0" Text="{Binding NewUser.Lastname}"/>
            </StackPanel>

        </StackPanel>

        <StackPanel Orientation="Horizontal" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="10,0,10,10">
            <Button Height="30" Width="70" Content="Close" Margin="10,0,0,0" Click="Close_Click"/>
            <Button Height="30" Width="70" Content="Save" Margin="10,0,0,0" Click="Save_Click" />
        </StackPanel>

    </Grid>
</Window>

C# Window1

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using WPF_App.Classes;

namespace WPF_App.ucWindow
{
    /// <summary>
    /// Interaktionslogik für Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void Save_Click(object sender, RoutedEventArgs e)
        {
            UserTask oUserTask = new UserTask();
            oUserTask.SaveUsers();
        }

        private void Close_Click(object sender, RoutedEventArgs e)
        {
            Close();
        }
    }
}

UserContent Class

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

namespace WPF_App.Classes
{
    public class UserContent
    {
        static int number = 1;
        public int Id { get; set; }
        public string Firstname { get; set; }
        public string Lastname { get; set; }
        public UserContent Copy() => new UserContent() { Id = number++, Firstname = this.Firstname, Lastname = this.Lastname };
    }
}

UserTask Class

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

namespace WPF_App.Classes
{
    class UserTask : INotifyPropertyChanged
    {
        public void SaveUsers()
        {
            this.ListOfUser.Add(NewUser.Copy());
            RaisePropertyChanged(nameof(SaveUsers));
        }


        public UserContent NewUser { get; set; } = new UserContent();

        public ObservableCollection<UserContent> ListOfUser { get; set; } = new ObservableCollection<UserContent>();

        public event PropertyChangedEventHandler PropertyChanged;
        private void RaisePropertyChanged(string propertyName) =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,676 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Peter Fleischer (former MVP) 19,231 Reputation points
    2022-01-25T05:30:19.007+00:00

    Hi Imilio,
    use this CodeBehind and DataGrid instead if ListView and it works fine:

    using System.Windows;
    using System.Windows.Controls;
    
    namespace Wpf_App
    {
      public partial class UserControl1 : UserControl
      {
        public UserControl1() => InitializeComponent();
        private void Add_Click(object sender, RoutedEventArgs e) => (new Window1() { DataContext = this.DataContext, Owner = Application.Current.MainWindow }).ShowDialog();
      }
    }
    
    -------------------------------------
    
    using System.Windows;
    using Wpf_App.Classes;
    
    namespace Wpf_App
    {
      public partial class Window1 : Window
      {
        public Window1() => InitializeComponent();
        private void Save_Click(object sender, RoutedEventArgs e) => ((UserTask)DataContext).SaveUsers();
        private void Close_Click(object sender, RoutedEventArgs e) => Close();
      }
    }