WPF:绑定数据网格不更新项属性

时间:2013-06-20 10:36:38

标签: wpf binding datagrid

我正在尝试实现我的第一个MVVM应用程序。我可以将数据绑定到数据网格中,但是我在项目中所做的更改不会触发模型的RaisePropertyChanged方法。

这是我的ViewModel

    public class UsersViewModel : BaseViewModel
{
    private static TOPEntities _context;
    private ObservableCollection<UserModel> _usersCollection;

           public UsersViewModel()
    {
        _usersCollection = new ObservableCollection<UserModel>(GetAllUsers());

    }
          public ObservableCollection<UserModel> UsersCollection
    {
        get { return _usersCollection; }
        set
        {
            if (_usersCollection != value)
            {
                _usersCollection = value;
                RaisePropertyChanged(() => UsersCollection);
            }
        }
    }
public static List<UserModel> GetAllUsers()
    {
        using (_context = new TOPEntities())
        {

            return _context.Users.Select
             (user => new UserModel
             {
                 Id_User = user.Id_User,
                 Name = user.Name,
                 Username = user.Username,
                 Language = user.Language,
                 Password = user.Password,
                 Profile = user.Profile

             }).ToList();

        }
    }

Model,实现了提供INotifyPropertyChanged

的NotificationObject类
    public class UserModel : NotificationObject
{
    #region Construction
    /// Constructs the default instance of a UserModel
    public UserModel()
    {

    }
    #endregion

    #region Model Attributes

    private int _id_User;
    private string _username;
    private string _password;
    private string _profile;
    private string _name;
    private string _language;

    #endregion

    #region Properties



    public int Id_User
    {
        get { return _id_User; }
        set
        {
            if (_id_User != value)
            {
               _id_User = value;
               RaisePropertyChanged(() => Id_User);
            }
        }
    }


    public string Username
    {
        get { return _username; }
        set
        {
            if (_username != value)
            {
                _username = value;
                RaisePropertyChanged(() => Id_User);
            }
        }
    }

    public string Password
    {
        get { return _password; }
        set
        {
            if (_password != value)
            {
                _password = value;
                RaisePropertyChanged(() => Id_User);
            }
        }
    }

    public string Profile
    {
        get { return _profile; }
        set
        {
            if (_profile != value)
            {
                _profile = value;
                RaisePropertyChanged(() => Id_User);
            }
        }
    }

    public string Name
    {
        get { return _name; }
        set
        {
            if (_name != value)
            {
                _name = value;
                RaisePropertyChanged(() => Name);
            }
        }
    }

    public string Language
    {
        get { return _language; }
        set
        {
            if (_language != value)
            {
                _language = value;
                RaisePropertyChanged(() => Language);
            }
        }
    }

    #endregion


}

}

最后,观点:

<Window x:Class="TOP2.Views.UsersView"
    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"
    mc:Ignorable="d"
    xmlns:viewModels="clr-namespace:TOP2.ViewModels"
    xmlns:local="TOP2"
    Title="Sample App"
    WindowStartupLocation="CenterScreen"
    Height="459"
    Width="795">
<Window.Resources>
    <viewModels:UsersViewModel x:Key="Windows1ViewModel" />
</Window.Resources>
<Grid DataContext="{StaticResource Windows1ViewModel}">
    <DataGrid ItemsSource="{Binding UsersCollection, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" AutoGenerateColumns="False" HorizontalAlignment="Left" Margin="81,51,0,0" VerticalAlignment="Top" Height="332" Width="622">
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Username, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
            <DataGridTextColumn Binding="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        </DataGrid.Columns>

    </DataGrid>

</Grid>

我忘记或做错了什么?

提前致谢!

的奥斯卡

3 个答案:

答案 0 :(得分:5)

非常感谢Loetn和AndrasSebö,你的线索非常有帮助!下面的解决方案已经采用了,它已经完美运行了!!!

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel; // ObservableCollection
using System.ComponentModel; // INotifyPropertyChanged
using System.Collections.Specialized; // NotifyCollectionChangedEventHandler
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ObservableCollectionTest
{
    class Program
    {
        static void Main(string[] args)
        {
            // ATTN: Please note it's a "TrulyObservableCollection" that's instantiated. Otherwise, "Trades[0].Qty = 999" will NOT trigger event handler "Trades_CollectionChanged" in main.
            // REF: http://stackoverflow.com/questions/8490533/notify-observablecollection-when-item-changes
            TrulyObservableCollection<Trade> Trades = new TrulyObservableCollection<Trade>();
            Trades.Add(new Trade { Symbol = "APPL", Qty = 123 });
            Trades.Add(new Trade { Symbol = "IBM", Qty = 456});
            Trades.Add(new Trade { Symbol = "CSCO", Qty = 789 });

        Trades.CollectionChanged += Trades_CollectionChanged;
        Trades.ItemPropertyChanged += PropertyChangedHandler;
        Trades.RemoveAt(2);

        Trades[0].Qty = 999;

        Console.WriteLine("Hit any key to exit");
        Console.ReadLine();

        return;
    }

    static void PropertyChangedHandler(object sender, PropertyChangedEventArgs e)
    {
        Console.WriteLine(DateTime.Now.ToString() + ", Property changed: " + e.PropertyName + ", Symbol: " + ((Trade) sender).Symbol + ", Qty: " + ((Trade) sender).Qty);
        return;
    }

    static void Trades_CollectionChanged(object sender, EventArgs e)
    {
        Console.WriteLine(DateTime.Now.ToString() + ", Collection changed");
        return;
    }
}

#region TrulyObservableCollection
public class TrulyObservableCollection<T> : ObservableCollection<T>
    where T : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler ItemPropertyChanged;

    public TrulyObservableCollection()
        : base()
    {
        CollectionChanged += new NotifyCollectionChangedEventHandler(TrulyObservableCollection_CollectionChanged);
    }

    void TrulyObservableCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.NewItems != null)
        {
            foreach (Object item in e.NewItems)
            {
                (item as INotifyPropertyChanged).PropertyChanged += new PropertyChangedEventHandler(item_PropertyChanged);
            }
        }
        if (e.OldItems != null)
        {
            foreach (Object item in e.OldItems)
            {
                (item as INotifyPropertyChanged).PropertyChanged -= new PropertyChangedEventHandler(item_PropertyChanged);
            }
        }
    }

    void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        NotifyCollectionChangedEventArgs a = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
        OnCollectionChanged(a);

        if (ItemPropertyChanged != null)
        {
            ItemPropertyChanged(sender, e);
        }
    }
}
#endregion

#region Sample entity
class Trade : INotifyPropertyChanged
{
    protected string _Symbol;
    protected int _Qty = 0;
    protected DateTime _OrderPlaced = DateTime.Now;

    public DateTime OrderPlaced
    {
        get { return _OrderPlaced; }
    }

    public string Symbol
    {
        get
        {
            return _Symbol;
        }
        set
        {
            _Symbol = value;
            NotifyPropertyChanged("Symbol");
        }
    }

    public int Qty
    {
        get
        {
            return _Qty;
        }
        set
        {
            _Qty = value;
            NotifyPropertyChanged("Qty");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
#endregion
}

答案 1 :(得分:3)

将此事件绑定到ObservableCollection的CollectionChanged事件:

private void ObservableCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null)
            {
                foreach (var item in e.NewItems)
                {
                    item.PropertyChanged += this.Item_PropertyChanged;
                }
            }

        if (e.OldItems != null)
        {
            foreach (var item in e.OldItems)
            {
                item.PropertyChanged -= this.Item_PropertyChanged;
            }
        }
    }

    private void Item_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        // do something
    }

答案 2 :(得分:2)

因为项目在集合中,集合本身不会更改。在将UserModel添加到集合之前,您必须在UsersViewModel类中订阅每个UserModel。

这是一个可能的解决方案:

http://social.msdn.microsoft.com/Forums/vstudio/en-US/c03b9edd-e9a9-4674-82d3-56caaf67d6d9/observablecollectiont-listen-for-changes-in-child-elements