7
votes

WPF: Louid DataGrid ne met pas à jour les propriétés d'éléments

J'essaie de mettre en œuvre ma première application MVVM. Je pourrais lier les données dans un DataGrid, mais les modifications que je fais dans des éléments ne déclenchent pas la méthode ShakPropertyChanged du modèle.

Ceci est mon point de vueModel p>

<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>


0 commentaires

3 Réponses :


2
votes

Parce que les articles sont dans la collection et la collection elle-même ne change pas. Vous devez vous abonner à la classe utilisateursviewModel chaque utilisateur utilisateur utilisateur avant de l'ajouter à la collection.

Voici une solution possible:

http://social.msdn.microsoft.com/forums/vstudio/en-us/c03b9edd-e9a9-4674-82d3-56aaf67d6d9/observaf67D6D9/OBServableCollectionT-Listen-for-changes-in-Child- éléments


3 commentaires

Désolé je suis vraiment débutant et cet exemple est comme O_O 'pour moi. Ok l'idée est une observablector "spécialisée" qui s'occupe des changements?


Cela semble vraiment câblé, me dis-tu que l'observablecollection ne met pas à jour les éléments des entrées de l'interface utilisateur?


Observablecollection notifie l'interface utilisateur si la collection elle-même a été modifiée (ajoutée, supprimée, supprimée, réinitialisée), mais ne notifie pas l'interface utilisateur si la propriété d'un élément de la collection a changé. Vérifiez la réponse de Loetn ci-dessous pour voir une solution de contournement possible.



3
votes

Liez cet événement à l'événement de collectionChanged de votre observablecollection:

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
    }


1 commentaires

Aucun problème. Heureux d'avoir pu aider. :)



5
votes

Merci beaucoup de Loetn et d'Andras Sebö¶, vos indices ont été très utiles! La solution ci-dessous a été celle que j'ai adoptée et elle a fonctionné parfaitement !!!

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
}


0 commentaires