C#WPF Datagrid不会对数据更新进行动态排序 [英] C# WPF Datagrid doesn't dynamically sort on data update

查看:161
本文介绍了C#WPF Datagrid不会对数据更新进行动态排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的datagrid有一些麻烦:



当我更新一些数据(从模型),它显示在我的DataGrid,但如果点击一个标题当我更新现有数据时,对列进行排序。



这里是 2 1示例 s




  • 如果我添加一个新值,它不会显示在最后(就像我不排序数据网格),但它显示在错误的地方(每次相同的地方)。

  • 如果我更新现有值,则当需要时,顺序不会更改。



我看过多个答案,但有些人说DataGridTextColumn不应该是一个问题... 所以我想知道这是因为字典...
我知道新数据的第一个问题与字典有关。



对象。

  public class Player:INotifyPropertyChanged 
{
私人字符串_id;
私有字符串_name;
private int _damage;
private int _heal;
private int _dps;
private int _hps;
private int _time = 1;

public Player(string id,string name)
{
_name = name;
_id = id;
}

public event PropertyChangedEventHandler PropertyChanged;

public string Id
{
get {return _id; }
private set
{
_id = value;
}
}

public string Name
{
get {return _name; }
private set
{
_name = value;
NotifyPropertyChanged(Name);
}
}

public int Damage
{
get {return _damage; }
set
{
_damage = value;
NotifyPropertyChanged(Damage);
Dps = _damage / _time;
}
}

public int Heal
{
get {return _heal; }
set
{
_heal = value;
NotifyPropertyChanged(Heal);
Hps = _heal / _time;
}
}

public int Dps
{
get {return _dps; }
private set
{
_dps = value;
NotifyPropertyChanged(Dps);
}
}

public int Hps
{
get {return _hps; }
private set
{
_hps = value;
NotifyPropertyChanged(Hps);
}
}

public int Time
{
get {return _time; }
set
{
_time = value;
Dps = _damage / _time;
Hps = _heal / _time;
}
}

private void NotifyPropertyChanged(string name)
{
if(PropertyChanged!= null)
PropertyChanged(this,new PropertyChangedEventArgs(name));
}

}

ObservableCollection

  public sealed class ShortList 
{
private static readonly ShortList instance = new ShortList();
private ObservableCollection< Player> playerList = new ObservableCollection< Player>();

private ShortList()
{
}

public static ShortList getShortList
{
get
{
返回实例;
}
}

public ObservableCollection< Player> getPlayerList
{
get
{
return playerList;
}
}

public void updatePlayer(string id,string name,int damage,int heal,int time)
{
播放器;
player = findPlayer(id);
if(player!= null)
{
player.Damage = player.Damage + damage;
player.Heal = player.Heal + heal;
player.Time = player.Time + time;
}
else
{
player = new Player(id,name);
player.Damage = damage;
player.Heal = heal;
player.Time = time;
playerList.Add(player);
}
}

public void clear()
{
playerList.Clear();
}

private Player findPlayer(string id)
{
foreach(playerList in playerList)
{
if(p.Id == id)
{
return p;
}
}
返回null;
}

}

XAML

 < DataGrid AutoGenerateColumns =FalseName =playerDataGridIsReadOnly =TrueItemsSource ={Binding}> 
< DataGrid.Columns>
< DataGridTextColumn Header =NomBinding ={Binding Name}MinWidth =35/>
< DataGridTextColumn Header =DegacesBinding ={Binding Damage}MinWidth =45/>
< DataGridTextColumn Header =DPSBinding ={Binding Dps}MinWidth =29/>
< DataGridTextColumn Header =SoinsBinding ={Binding Heal}MinWidth =35/>
< DataGridTextColumn Header =HPSBinding ={Binding Hps}MinWidth =29/>
< /DataGrid.Columns>
< / DataGrid>

窗口后面的代码

  public partial class MiniParser:Window 
{
public MiniParser()
{
InitializeComponent();
playerDataGrid.ItemsSource = ShortList.getShortList.getPlayerList;
temporyFill();
}

private void temporyFill()
{
ShortList.getShortList.updatePlayer(1234,ABCD,100,0,2);
ShortList.getShortList.updatePlayer(1234,ABCD,100,0,0);
ShortList.getShortList.updatePlayer(123,ABC,50,0,1);
ShortList.getShortList.updatePlayer(234,ABC,0,50,1);
ShortList.getShortList.updatePlayer(345,BCD,1000,25,25);
ShortList.getShortList.updatePlayer(456,CDE,250,0,25);
}

private void startMI_Click(object sender,RoutedEventArgs e)
{
ShortList.getShortList.updatePlayer(5678,BABA,100,100, 100);
ShortList.getShortList.updatePlayer(1234,ABCD,100,0,0);
}
}

当然大多数代码都在那里进行测试目的...但是想法是,模型正在更新,视图需要反映变化(甚至排序)。

解决方案

我找到了一个解决方案,迄今为止:



问题是ObservableCollection在更改字段值时不会触发事件CollectionChanged在一个已经在您的ObservableCollection中的对象。 (可能是因为你不改变它的参考)。



这里有一个例子:

  ObservableCollection< MyObject> myCollection = new ObservableCollection< MyObject>(); 
myCollection.add(CollectionChanged,Yes);
//假设我有一个方法来找到一个带有第一个字符串的对象,并更改第二个字符串
myCollection.change(CollectionChanged,No);

你可以猜到,第二部分我改变了现有对象的一个​​字段时,CollectionChanged没有t触发...



所以我实现的解决方案如下:

  class ObsCollection< T> :ObservableCollection< T> 
{
public void UpdateCollection()
{
OnCollectionChanged(new NotifyCollectionChangedEventArgs(
NotifyCollectionChangedAction.Reset));
}
}

所有你需要做的是创建新的收集,然后当您更改现有对象的字段值时,调用UpdateCollection()方法。



此解决方案来自吴学松。



我想说Rachel也是一个很大的帮助。


I'm having some trouble with my datagrid :

When I update some data (from the model) it shows on my DataGrid, but if click on a header to sort the column it begins to go sideways when I update existing data.

Here's 2 1 examples :

  • If I add a new value, it doesn't appear at the end (like it does when I don't sort the datagrid) but it shows at the wrong place (same place every time).
  • If I update an existing value, the order never changes when it needs to do so.

I've seen multiple answers but some say DataGridTextColumn shouldn't be a problem... So I was wondering if it was because of the dictionary... I know that the first problem with new data had something to do with the dictionary.

Object.

    public class Player : INotifyPropertyChanged
{
    private string _id;
    private string _name;
    private int _damage;
    private int _heal;
    private int _dps;
    private int _hps;
    private int _time = 1;               

    public Player(string id, string name)
    {
        _name = name;
        _id = id;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public string Id 
    {
        get { return _id; }
        private set
        {
            _id = value;
        }
    }

    public string Name
    {
        get { return _name; }
        private set
        {                
            _name = value;                
            NotifyPropertyChanged("Name");                
        }
    }

    public int Damage
    {
        get { return _damage; }
        set
        {
            _damage = value;                
            NotifyPropertyChanged("Damage");
            Dps = _damage / _time;
        }
    }

    public int Heal
    {
        get { return _heal; }
        set
        {
            _heal = value;
            NotifyPropertyChanged("Heal");
            Hps = _heal / _time;
        }
    }

    public int Dps
    {
        get { return _dps; }
        private set
        {
            _dps = value;
            NotifyPropertyChanged("Dps");
        }
    }

    public int Hps
    {
        get {return _hps; }
        private set
        {
            _hps = value;
            NotifyPropertyChanged("Hps");
        }
    }

    public int Time
    {
        get { return _time; }
        set
        {
            _time = value;
            Dps = _damage / _time;
            Hps = _heal / _time;
        }
    }

    private void NotifyPropertyChanged(string name)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(name));
    }

}

ObservableCollection

public sealed class ShortList
{
    private static readonly ShortList instance =  new ShortList();
    private ObservableCollection<Player> playerList = new ObservableCollection<Player>();

    private ShortList()
    {
    }

    public static ShortList getShortList
    {
        get
        {
            return instance;
        }
    }

    public ObservableCollection<Player> getPlayerList
    {
        get
        {
            return playerList;
        }
    }

    public void updatePlayer(string id, string name, int damage, int heal, int time) 
    {
        Player player;
        player = findPlayer(id);
        if (player != null)
        {                
            player.Damage = player.Damage + damage;
            player.Heal = player.Heal + heal;
            player.Time = player.Time + time;                
        }
        else
        {                
            player = new Player(id, name);
            player.Damage = damage;
            player.Heal = heal;
            player.Time = time;
            playerList.Add(player);
        }                       
    }

    public void clear()
    {
        playerList.Clear();
    }

    private Player findPlayer(string id)
    {
        foreach (Player p in playerList)
        {
            if (p.Id == id)
            {
                return p;
            }
        }
        return null;
    }

}

XAML

<DataGrid AutoGenerateColumns="False"Name="playerDataGrid" IsReadOnly="True" ItemsSource="{Binding}">
    <DataGrid.Columns>
       <DataGridTextColumn Header="Nom" Binding="{Binding Name}" MinWidth="35"/>
       <DataGridTextColumn Header="Degats" Binding="{Binding Damage}" MinWidth="45" />
       <DataGridTextColumn Header="DPS" Binding="{Binding Dps}" MinWidth="29" />
       <DataGridTextColumn Header="Soins" Binding="{Binding Heal}" MinWidth="35" />
       <DataGridTextColumn Header="HPS" Binding="{Binding Hps}" MinWidth="29" />
   </DataGrid.Columns>
</DataGrid>

Code behind the window

public partial class MiniParser : Window
{
        public MiniParser()
        {            
            InitializeComponent();
            playerDataGrid.ItemsSource = ShortList.getShortList.getPlayerList;
            temporyFill();
        }

        private void temporyFill()
        {
            ShortList.getShortList.updatePlayer("1234", "ABCD", 100, 0, 2);
            ShortList.getShortList.updatePlayer("1234", "ABCD", 100, 0, 0);
            ShortList.getShortList.updatePlayer("123", "ABC", 50, 0, 1);
            ShortList.getShortList.updatePlayer("234", "ABC", 0, 50, 1);
            ShortList.getShortList.updatePlayer("345", "BCD", 1000, 25, 25);
            ShortList.getShortList.updatePlayer("456", "CDE", 250, 0, 25);
        }

        private void startMI_Click(object sender, RoutedEventArgs e)
        {
            ShortList.getShortList.updatePlayer("5678", "BABA", 100, 100, 100);
            ShortList.getShortList.updatePlayer("1234", "ABCD", 100, 0, 0);            
        }
}

Of course most of the code behind is there for testing purpose... But the idea is that the model is being updated and the view needs to reflect the changes (Even the sorting).

解决方案

I found a solution, so far so good :

The problem was that ObservableCollection doesn't trigger the event "CollectionChanged" when you change the value of a field in an object which is already in your ObservableCollection. (Possibly because you don't change the reference to it).

Here's an example :

ObservableCollection<MyObject> myCollection = new ObservableCollection<MyObject>();
myCollection.add("CollectionChanged","Yes");
//Let's say I had a method to find a object with the first string and to change the second string
myCollection.change("CollectionChanged", "No");

As you can guess, the second part when I changed a field of my existing object the CollectionChanged didn't trigger...

So the solution I implemented is the following :

class ObsCollection<T> : ObservableCollection<T>
    {
        public void UpdateCollection()
        {
            OnCollectionChanged(new NotifyCollectionChangedEventArgs(
                            NotifyCollectionChangedAction.Reset));
        }
    }

All you have to do is create the new type of collection and then when you change a field value of an existing object, call the UpdateCollection() method.

This solution is from Wu Xuesong.

I'd like to say Rachel as been also a big help.

这篇关于C#WPF Datagrid不会对数据更新进行动态排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆