簡體   English   中英

C#WPF Datagrid不會在數據更新時動態排序

[英]C# WPF Datagrid doesn't dynamically sort on data update

我的datagrid遇到了一些麻煩:

當我更新一些數據(來自模型)時,它會顯示在我的DataGrid上,但是如果單擊標題以對列進行排序,那么當我更新現有數據時,它就會開始橫擺。

這里有 2 1例 S:

  • 如果我添加一個新值,它不會出現在末尾(就像我不對數據網格排序時一樣),但是它顯示在錯誤的位置(每次都在同一位置)。
  • 如果我更新現有值,則訂單永遠不會在需要時更改。

我已經看到了多個答案,但有人說DataGridTextColumn應該不成問題... 所以我想知道是否是由於字典的緣故... 我知道新數據的第一個問題與字典有關。

賓語。

    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>

窗口后面的代碼

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);            
        }
}

當然,后面的大多數代碼都用於測試目的...但是想法是模型正在更新,視圖需要反映更改(即使是排序)。

當屬性更新時,您不會引發PropertyChanged事件。 這意味着name""更改為"Test"的新項目,或已更改的現有項目,都不會引發PropertyChanged事件以使UI知道值已更改並且需要更新。

要解決此問題,請使屬性在更改時引發PropertyChanged事件。

public class Player : INotifyPropertyChanged
{
    private string _name;
    public string Name 
    {
        get { return _name; }
        set
        {
            if (_name != value)
            {
                _name = value;
                RaisePropertyChanged("Name");
            }
        }
    }

另外,我正在重新閱讀您的問題,我不知道您對ObservableDictionary所做的事情,但是我建議您進行更改,以便您的DataGrid直接綁定到ObservableCollection<Player> 我懷疑這是您問題的一部分。

var playerCollection = new ObservableCollection<Player>();
playerCollection.Add(new Player { Name = "Test 1" });
playerCollection.Add(new Player { Name = "Test 2" });
playerCollection.Add(new Player { Name = "Test 3" });

playerDataGrid.ItemsSource = playerCollection;

我找到了一個解決方案,到目前為止一切順利:

問題是,當您更改ObservableCollection中已經存在的對象中字段的值時,ObservableCollection不會觸發事件“ CollectionChanged”。 (可能是因為您沒有更改對它的引用)。

這是一個例子:

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");

可以猜到,第二部分是當我更改現有對象的字段CollectionChanged時未觸發...

因此,我實現的解決方案如下:

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

您要做的就是創建新的集合類型,然后在更改現有對象的字段值時,調用UpdateCollection()方法。

此解決方案來自吳學松。

我想說Rachel也是很大的幫助。

移動任何看起來像這樣的代碼:

this.NotifyPropertyChanged("somepropertyname");

進入屬性的setter方法。 這就是二傳手的目的。

另外,我還建議您使用ObservableCollection<T>代替ObservableDictionary<TKey,TValue> 對於WPF綁定,它們非常常見。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM