简体   繁体   中英

WPF MVVM binding - list is not refreshing

I'm getting a list from the database. I have a button that adds a new user and then the list should refresh. However, this does not happen. Somebody help me?

Model:

namespace ManagementProjectSystem.Model
{
    public class User
    {
        [Key]
        public int UserID { get; set; }
        public int UserRoleID { get; set; }
        public string Name { get; set; }
        public string Surname { get; set; }
        public string Login { get; set; }
        public string Password { get; set; }
        public DateTime DateCreateAccount { get; set; }

        public virtual ICollection<UserContact> UserContacts { get; set; }
        public virtual UserRole UserRole { get; set; }

    }
}

ViewModel:

using ManagementProjectSystem.DAL;
using ManagementProjectSystem.Model;
using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;

namespace ManagementProjectSystem.ViewModel
{
    class AdminViewModel : BindableBase
    {
        private readonly ManagementProjectSystemContext dbContext = new ManagementProjectSystemContext();

        private List<User> _Users { get; set; }
        private string _UserRole { get; set; }
        private string _Name { get; set; }
        private string _Surname { get; set; }
        private string _Login { get; set; }
        private string _Password { get; set; }

        [Obsolete]
        public List<User> Users
        {
            get
            {
                return _Users = dbContext.User.ToList();
            }
            set
            {
                _Users = value;
                OnPropertyChanged(() => Users);
            }
        }

        public List<UserRole> UsersRole
        {
            get
            {
                return dbContext.UserRole.ToList();
            }
        }

        public string UserRole
        {
            get
            {
                return _UserRole;
            }
            set
            {
                _UserRole = value;
                RaisePropertyChanged(UserRole); //OnPropertyChanged(() => UserRole);
            }
        }

        public string Name
        {
            get
            {
                return _Name;
            }
            set
            {
                _Name = value;
                RaisePropertyChanged(Name); //OnPropertyChanged(() => UserRole);
            }
        }

        public string Surname
        {
            get
            {
                return _Surname;
            }
            set
            {
                _Surname = value;
                RaisePropertyChanged(Surname); //OnPropertyChanged(() => UserRole);
            }
        }

        public string Login
        {
            get
            {
                return _Login;
            }
            set
            {
                _Login = value;
                RaisePropertyChanged(Login); //OnPropertyChanged(() => UserRole);
            }
        }

        public string Password
        {
            get
            {
                return _Password;
            }
            set
            {
                _Password = value;
                RaisePropertyChanged(Password); //OnPropertyChanged(() => UserRole);
            }
        }

        public ICommand AddUserButton { get; set; }

        public AdminViewModel()
        {
            AddUserButton = new DelegateCommand(AddUser);
        }

        private void AddUser()
        {
            MessageBox.Show(_UserRole + " " + _Name + " " + _Surname + " " + _Login + " " + _Password);
            var userRole = dbContext.UserRole.Where(n => n.Nazwa.ToString().Equals(_UserRole)).SingleOrDefault();
            int userRoleID = userRole.UserRoleID;

            User user = new User() {Name = _Name, Surname = _Surname, Login = _Login, Password = _Password, DateCreateAccount = DateTime.Now, UserRoleID = userRoleID };

            dbContext.User.Add(user);
            dbContext.SaveChanges();

            //_Users = dbContext.User.ToList();
        }
    }
}

View - XAML

<Window x:Class="ManagementProjectSystem.Admin"
        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:ManagementProjectSystem"
        mc:Ignorable="d"
        Title="Admin" Height="450" Width="800">

    <Window.Resources>
        <Style x:Key="ListViewStyle" TargetType="{x:Type GridViewColumnHeader}">
            <Setter Property="HorizontalContentAlignment" Value="Left" />
        </Style>
    </Window.Resources>

    <Grid>
        <TabControl>
            <TabItem Header="Users">
                <Grid Background="RosyBrown">

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

                    <ListView Grid.Column="0" Grid.Row="0" Margin="10" ItemsSource="{Binding Users}" HorizontalContentAlignment="Left">
                        <ListView.View>
                            <GridView>
                                <GridViewColumn HeaderContainerStyle="{StaticResource ListViewStyle}" Header="Name" DisplayMemberBinding="{Binding Name}" />
                                <GridViewColumn HeaderContainerStyle="{StaticResource ListViewStyle}" Header="Surname"  DisplayMemberBinding="{Binding Surname}" />
                            </GridView>
                        </ListView.View>
                    </ListView>

                    <Grid Margin="10" Grid.Column="1" Grid.Row="0">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>
                        <Label>Name:</Label>
                        <TextBox Grid.Column="1" Margin="10" Text="{Binding Path = Name}"/>
                        <Label Grid.Row="1">Surname</Label>
                        <TextBox Grid.Row="1" Grid.Column="1" Margin="10" Text="{Binding Path = Surname}"/>
                        <Label Grid.Row="2">Login:</Label>
                        <TextBox Grid.Row="2" Grid.Column="1" Margin="10" Text="{Binding Path = Login}"/>
                        <Label Grid.Row="3">Password:</Label>
                        <TextBox Grid.Row="3" Grid.Column="1" Margin="10" Text="{Binding Path = Password}"/>
                        <Label Grid.Row="4">User role:</Label>
                        <ComboBox Grid.Row="4" Grid.Column="1" Margin="10" ItemsSource="{Binding Path = UsersRole}" DisplayMemberPath="Nazwa"
                                  SelectedValuePath="Nazwa" SelectedValue="{Binding UserRole}">

                        </ComboBox>

                        <Button Grid.Row="5" Grid.Column="1" Command="{Binding AddUserButton}">Add user</Button>
                    </Grid>
                </Grid>

            </TabItem>
            <TabItem Header="TabItem">
                <Grid Background="#FFE5E5E5"/>
            </TabItem>
        </TabControl>
    </Grid>
</Window>

View - XAML.cs

namespace ManagementProjectSystem
{
    public partial class Admin : Window
    {
        public Admin()
        {
            InitializeComponent();
            AdminViewModel vm = new AdminViewModel();
            this.DataContext = vm;
        }
    }
}

I'm just starting to learn WPF and learn the MVVM pattern. I apologize for my English if there is something wrong written. I use Prism and Entity Framework. What can I improve in the code to make the list refresh work after adding a new user? And generally the code is good?

You can use ObservableCollection if you are going to add (or remove) individual items from it and want the View to update when that happens. It's not mandatory to use ObservableCollection , but if you don't, then the UI will need to reload the entire collection when items are added (or removed). It's up to you to decide whether that's a performance concern.

Currently, you are reloading the collection from the data store on every access of the Users property. This is not good.

Option 1 - Keep using List<User> :

I suggest first changing the Users property to avoid loading from the data store on every Get:

public List<User> Users
{
    get
    {
        if (_Users == null)
        {
            _Users = dbContext.User.ToList();
        }
        return _Users;
    }
    set
    {
        _Users = value;
        OnPropertyChanged(() => Users);
    }
}

Then in the AddUser method, add the new User to the list and raise the PropertyChanged event for the Users property:

...
dbContext.User.Add(user);
dbContext.SaveChanges();
_Users.Add(user);
OnPropertyChanged(() => Users);

Option 2 - Use ObservableCollection<User> :

If you do want to use ObservableCollection as suggested in comments, make the following changes:

This line:

private List<User> _Users { get; set; }

Becomes:

private ObservableCollection<User> _Users { get; set; }

The Users property becomes:

public List<User> Users
{
    get
    {
        if (_Users == null)
        {
            _Users = new ObservableCollection<User>(dbContext.User);
        }
        return _Users;
    }
    set
    {
        _Users = value;
        OnPropertyChanged(() => Users);
    }
}

And remove the OnPropertyChanged(() => Users); from the AddUser method (because the ObservableCollection will fire its own CollectionChanged event instead when you add to the collection, which will update the View).

Note: in the above, I am assuming dbContext.User implements IEnumerable<User> so a ToList() is unnecessary if passing it to the ObservableCollection constructor (this avoids creating a useless list during that step).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM