【问题标题】:Why collectionviewsource not updating the datagrid when clicking a button?为什么单击按钮时collectionviewsource 不更新数据网格?
【发布时间】:2016-02-25 02:41:50
【问题描述】:

我有两个视图模型,一个是 mainViewModel,另一个是 parentViewModel。我将 mainViewModel 设置为我的主窗口网格的数据上下文,并将 parentViewModel 设置为我的数据网格的数据上下文。我尝试使用实体框架生成的模型来更新数据网格,但在实现 INotifyPropertyChange 时出现错误,因此我创建了一个自定义模型并将数据从实体框架模型映射到我的自定义模型。

父视图模型:

在这种情况下,Parent 类是实体框架生成的模型,Parents 类是我的自定义模型。

public class ParentViewModel : INotifyPropertyChanged 
{
    #region Constructor
    /// <summary>
    /// Initializes a new instance of Parent ViewModel class.
    /// </summary>
    public ParentViewModel()
    {
        _addParentCommand = new AddParentCommand(AddParent, IsExecutable);
        Parentss = new Parents()
        {
            PLastName = null,
            PFirstName = null,
            PMiddleName = null,
            PAddress = null,
            PContactNo = null,
            PEmail = null,
            PUsername = null,
            PPassword = null,
            ValidationString = null
        };
        _parentCollection = new ObservableCollection<Parent>();
        _parentsCollection = new ObservableCollection<Parents>();
        //ParentsCollection = new ObservableCollection<Parents>();
        _parentList = new List<Parent>();
        _parentsList = new List<Parents>();
        ViewSource = new CollectionViewSource();
        ViewSource.Source = ParentsCollection;
        Load();
    }
    #endregion

    #region Events
    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion

    #region Methods
    /// <summary>
    /// Checks if the application can execute a method.
    /// </summary>
    /// <param name="context">Data context</param>
    /// <returns>bool</returns>
    public bool IsExecutable(object context)
    {
        if (context != null)
        {
            var s = context as string;
            s = s.Trim();
            if (string.IsNullOrWhiteSpace(s))
            {
                return false;
            }
            return true;
        }
        return false;
    }

    /// <summary>
    /// Loads the data from the database when the application starts.
    /// </summary>
    public void Load()
    {
        using (RegistrationEntities registrationContext = new RegistrationEntities())
        {
            _parentList = registrationContext.Parents.ToList();


            for (int i = 0; i < _parentList.Count; i++)
            {
                Parents = new Parents()
                {
                    PId = _parentList[i].P_Id,
                    PLastName = _parentList[i].P_LastName,
                    PFirstName = _parentList[i].P_FirstName,
                    PMiddleName = _parentList[i].P_MiddleName,
                    PAddress = _parentList[i].P_Address,
                    PContactNo = _parentList[i].P_ContactNo,
                    PEmail = _parentList[i].P_Email,
                    PUsername = _parentList[i].P_Username,
                    PPassword = _parentList[i].P_Password,
                    PCreatedOn = _parentList[i].P_CreatedOn,
                    PUpdatedAt = _parentList[i].P_UpdatedAt
                };

                _parentsCollection.Add(Parents);
                //ParentsCollection.Add(Parents);
            }
        }
    }

    public void Load2()
    {
        //for (int i = 0; i < _parentsList.Count; i++)
        //{
        //    _parentsCollection.Add(_parentsList[i]);
        //}
    }

    /// <summary>
    /// Add a new Parent.
    /// </summary>
    /// <param name="context">Data context</param>
    public void AddParent(object context)
    {
        using (RegistrationEntities registrationContext = new RegistrationEntities())
        {
            Parent parent = new Parent
            {
                P_LastName = Parentss.PLastName,
                P_FirstName = Parentss.PFirstName,
                P_MiddleName = Parentss.PMiddleName,
                P_Address = Parentss.PAddress,
                P_ContactNo = Parentss.PContactNo,
                P_Email = Parentss.PEmail,
                P_Username = Parentss.PUsername,
                P_Password = Encrypt(Parentss.PPassword),
                P_CreatedOn = DateTime.Now.Date + DateTime.Now.TimeOfDay,
                P_UpdatedAt = DateTime.Now.Date + DateTime.Now.TimeOfDay
            };

            registrationContext.Parents.Add(parent);

            try
            {
                registrationContext.SaveChanges();

                _parentList = registrationContext.Parents.ToList();

                _parentsCollection.Clear();
                //ParentsCollection.Clear();

                for (int i = 0; i < _parentList.Count; i++)
                {
                    Parents = new Parents()
                    {
                        PId = _parentList[i].P_Id,
                        PLastName = _parentList[i].P_LastName,
                        PFirstName = _parentList[i].P_FirstName,
                        PMiddleName = _parentList[i].P_MiddleName,
                        PAddress = _parentList[i].P_Address,
                        PContactNo = _parentList[i].P_ContactNo,
                        PEmail = _parentList[i].P_Email,
                        PUsername = _parentList[i].P_Username,
                        PPassword = _parentList[i].P_Password,
                        PCreatedOn = _parentList[i].P_CreatedOn,
                        PUpdatedAt = _parentList[i].P_UpdatedAt
                    };

                    _parentsCollection.Add(Parents);
                     ViewSource.View.Refresh();
                    //ParentsCollection.Add(Parents);

                }

                MessageBox.Show("Success!");

                Parentss.PLastName = null;
                Parentss.PFirstName = null;
                Parentss.PMiddleName = null;
                Parentss.PAddress = null;
                Parentss.PContactNo = null;
                Parentss.PEmail = null;
                Parentss.PUsername = null;
                Parentss.PPassword = null;
            }
            catch (DbEntityValidationException ex)
            {
                foreach (var eve in ex.EntityValidationErrors)
                {
                    MessageBox.Show(String.Format("Entity of type \"{0}\" in state \"{1}\" has the following validation errors: ", eve.Entry.Entity.GetType().Name, eve.Entry.State));
                    foreach (var ve in eve.ValidationErrors)
                    {
                        MessageBox.Show(String.Format("- Property: \"{0}\", Value: \"{1}\", Error: \"{2}\"", ve.PropertyName, eve.Entry.CurrentValues.GetValue<object>(ve.PropertyName), ve.ErrorMessage));
                    }
                }
            }
        }
    }

    public string Encrypt(string password)
    {
        MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
        md5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(password));
        byte[] result = md5.Hash;
        StringBuilder str = new StringBuilder();

        for (int i = 0; i < result.Length; i++)
        {
            str.Append(result[i].ToString("x2"));
        }

        return str.ToString();
    }
    #endregion

    #region Commands and Properties
    private ICommand _addParentCommand;

    /// <summary>
    /// Gets or sets an ICommand interface.
    /// </summary>
    public ICommand AddParentCommand
    {
        get { return _addParentCommand; }
        set { _addParentCommand = value; }
    }

    /// <summary>
    /// Gets or sets a Parent class.
    /// </summary>
    public Parents Parentss
    {
        get;
        set;
    }

    public Parents Parents
    {
        get;
        set;
    }

    private List<Parent> _parentList;

    public List<Parent> ParentList
    {
        get { return _parentList; }
        set { _parentList = value; OnPropertyChanged("ParentList"); }
    }

    private ObservableCollection<Parent> _parentCollection;

    public ObservableCollection<Parent> ParentCollection
    {
        get { return _parentCollection; }
        set { _parentCollection = value; }
    }

    private List<Parents> _parentsList;

    public List<Parents> ParentsList
    {
        get { return _parentsList; }
        set { _parentsList = value; }
    }

    private ObservableCollection<Parents> _parentsCollection;

    public ObservableCollection<Parents> ParentsCollection
    {
        get { return _parentsCollection; }
        set { _parentsCollection = value; }
    }

    public CollectionViewSource ViewSource { get; set; }

    #endregion
}

XAML:

 <Grid DataContext="{StaticResource mainViewModel}">

<DataGrid x:Name="dgvParent" Grid.Row="1" HorizontalAlignment="Stretch" Height="Auto" VerticalAlignment="Stretch" Width="Auto" SelectionMode="Single" BorderThickness="2" Style="{StaticResource AzureDataGrid}" AutoGenerateColumns="False" AlternatingRowBackground="LightBlue" ItemsSource="{Binding ViewSource.View}" DataContext="{DynamicResource parentViewModel}" CanUserAddRows="False">
                    <DataGrid.Columns>
                        <DataGridTextColumn Binding="{Binding PId}" FontWeight="Bold" Header="Id" />
                        <DataGridTextColumn Binding="{Binding PLastName}" FontWeight="Bold" Header="Last Name" />
                        <DataGridTextColumn Binding="{Binding PFirstName}" FontWeight="Bold" Header="First Name" />
                        <DataGridTextColumn Binding="{Binding PMiddleName}" FontWeight="Bold" Header="Middle Name" />
                        <DataGridTextColumn Binding="{Binding PAddress}" FontWeight="Bold" Header="Address" />
                        <DataGridTextColumn Binding="{Binding PContactNo}" FontWeight="Bold" Header="Contact Number" />
                        <DataGridTextColumn Binding="{Binding PEmail}" FontWeight="Bold" Header="Email" />
                        <DataGridTextColumn Binding="{Binding PCreatedOn}" FontWeight="Bold" Header="Created On" />
                        <DataGridTextColumn Binding="{Binding PUpdatedAt}" FontWeight="Bold" Header="Updated At" />
                    </DataGrid.Columns>
                </DataGrid>

【问题讨论】:

    标签: c# wpf entity-framework mvvm datagrid


    【解决方案1】:

    这就是我在项目中所做的:

    public ICollectionView MyView{ get; set; }
    
    //ctor
    public ParentViewModel()
    {
        //...
        ParentsCollection= new ObservableCollection<Parents>();
        MyView= CollectionViewSource.GetDefaultView(ParentsCollection);
        //...
    }
    
    
    <DataGrid ItemsSource="{Binding MyView}"/>
    

    顺便说一句。如果绑定不起作用,请在运行时使用 Snoop 检查 DataContextBindingExpressions。它总是两者之一;)

    【讨论】:

      【解决方案2】:

      我的答案并不是真正的答案——更像是一系列的抱怨和建议——但它不适合 cmets 框,所以我把它放在这里。

      1. 这里有很多清理和改进的空间,尤其是当涉及到您的变量名和多个外观相似的变量定义时。
      2. 您似乎没有包含按钮定义,因此我们不知道您的 AddParentCommand 是否正在执行。
      3. 如果您每次都想彻底清除和重建集合,那么拥有ObservableCollection 毫无意义;您可以将其保留为 List 并通知列表的属性已更改,但正确利用 ObservableCollection 的力量会更好。
      4. 我不相信你的 CollectionViewSource 能给你带来任何好处,除了可能帮助你从你实际上并没有在你的财产上筹集 PropertyChanged 的事实中恢复过来。

      尝试在没有数据库持久性的情况下首先使用更简单的代码版本。

      【讨论】:

      • -1 for 3. 因为它是 ObservableCollection 的好处 -> 只需创建一次实例并使用 Clear()、Add()、Remove() 来更改它。如果您使用 ICollectionView 进行排序、过滤和导航,那么只需创建一次实例就更容易了。否则每次创建 ObservableCollection 的新实例时都需要重新创建 ICollectionView
      • @blindmeis 我只是指出这样一个事实,即调用Clear 并从头开始重建ObservableCollection 似乎不太理想,而不是根据需要调用AddRemove。老实说,我认为我们在同一页面上,-1 是没有根据的。我实际上并不是建议使用 List 而不是 ObservableCollection 但这或多或少是 OP 使用此代码完成的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-17
      相关资源
      最近更新 更多