redux17
redux17

Reputation: 685

ListView Delete Refresh does not work?

I'm developing WPF MVVM Application with the basic CRUD functionality. I use ListView that contains and show data for users. When I Add or Update some User ListVew is refreshing immediately, but after Delete command ListView is not refreshing. In that case I have to close application and run again to make refresh ListView.

XAML

<ListView  Name="LstUsers" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
              ScrollViewer.VerticalScrollBarVisibility="Disabled" IsSynchronizedWithCurrentItem="True"
              ItemsSource="{Binding ViewList.View, UpdateSourceTrigger=PropertyChanged, IsAsync=True}"
              SelectedItem="{Binding CurrentSelectedUser, Mode=TwoWay}" Height="150" Margin="0,40,10,260" Grid.ColumnSpan="2" Grid.RowSpan="2">

VIEW MODEL

private ObservableCollection<User> _users;


public UserViewModel()
{

  _users = new ObservableCollection<User>(GetAllUsers());

// Paging Control
  ViewList = new CollectionViewSource();
  ViewList.Source = Users;
  ViewList.Filter += new FilterEventHandler(ViewFilter);

  CurrentPageIndex = 0;
  itemcount = Users.Count;
  CalculateTotalPages();
}

#region DeleteCommand

    public ICommand DeleteUserCmd
    {
        get { return new RelayCommand(k => DeleteUser(CurrentSelectedUser)); }
    }

    // Delete user from database.
    private void DeleteUser (User user)
    {
        if(CurrentSelectedUser != null)
        {
            using (var userManager = new UserManager())
            {
                MessageBoxResult msgResult = MessageBox.Show("Are you sure to delete user?", "Delete user?", System.Windows.MessageBoxButton.OKCancel, MessageBoxImage.Asterisk);
                if (msgResult == System.Windows.MessageBoxResult.Yes)
                {
                    return;
                }
                userManager.Delete(user);
                MessageBox.Show("User is deleted!", "Confirm!", MessageBoxButton.OK, MessageBoxImage.Asterisk);

                // Refresh Listview after delete record.
                Users.Remove(user);
            }
        }
        else
            MessageBox.Show("You must select user!", "Warning!", MessageBoxButton.OK, MessageBoxImage.Exclamation);  
    }

    #endregion

MODEL

public CollectionViewSource ViewList { get; set; }

public ObservableCollection<User> Users
    {
        get
        {
            return _users;
        }
        set
        {
            _users = value;
            OnPropertyChanged("Users");
        }
    }

Upvotes: 1

Views: 966

Answers (3)

Joe
Joe

Reputation: 7004

Where exactly is the "Object reference not set to an instance of an object."? I suspect it's on this line:

UserId = value.UserId;

When you delete the selected user, the list gets updated (At last! Hurah) - when this happens the CurrentSelectedUser doesn't exist anymore (it's just got deleted) so I suspect the binding is set to null. (nothing selected).

That calls the set{} method with value=null. So value.UserId; throws the exception.

You need to handle the CurrentSelectedUser being set to null like this or similar:

public User CurrentSelectedUser
{
    get { return _user; }
    set
    {
        if (value != null)
        {
            UserId = value.UserId;
            FirstName = value.FirstName;
            LastName = value.LastName;
            Username = value.Username;
            Password = value.Password;
            UserTypeId = value.UserTypeId;
        }
        else
        {
             UserId = -1;// or other "NO USER" condition
             //etc etc
        }
        OnPropertyChanged("CurrentSelectedUser");
    }
}

Upvotes: 0

redux17
redux17

Reputation: 685

I added this line

Users.Remove(Users.Where(i => i.UserId == user.UserId).Single());

instead of

Users.Remove(user);

and now when I debug code after Delete Command Count Users is minus one but application failed on

Object reference not set to an instance of an object.

public User CurrentSelectedUser
    {
        get { return _user; }
        set
        {
            UserId = value.UserId;
            FirstName = value.FirstName;
            LastName = value.LastName;
            Username = value.Username;
            Password = value.Password;
            UserTypeId = value.UserTypeId;
            OnPropertyChanged("CurrentSelectedUser");
        }
    }

Upvotes: 1

Joe
Joe

Reputation: 7004

Edit: Was this a translation error? I notice Korisnici is bosnian for "The Users"

What is ViewList.View that you're binding your ItemsSource to?

Anyway, you're presumably binding the items to the property "Users", hence why you are calling OnPropertyChanged("Users") when you want to update your list.

However, you're removing the user from "Korisnici":

// Refresh Listview-a after delete record.
Korisnici.Remove(user);
OnPropertyChanged("Users");

Not the "Users" collection. unless Korisnici.Remove is a method you have created? What is Korisnici? I think you want:

// Refresh Listview-a after delete record.
Users.Remove(user);

Note, you don't need the OnPropertyChanged("Users") - this is managed by the ObservableCollection, which implements INotifyCollectionChanged itself to notify of changes to the collection.

Upvotes: 0

Related Questions