Frage

Ich habe eine Basis DependencyObject-Klasse, wo ich eine Methode, die eine Aufgabe übernimmt, bekommt die Eigenschaften und für jede Eigenschaft, die eine Art ist, dass implementiert INotifyPropertyChanged, füge ich einen neuen PropertyChangedEventHandler. Jetzt in der Handler-Methode, wird es die Parameter eines Objekts „Sender“ und die PropertyChangedEventArgs „e“. Meine Frage ist, Wer weiß, wie dynamisch die Eigenschaftsnamen zu erhalten, wenn Absender eine Eigenschaft eines Typs ist, dass Geräte der INotifyPropertyChanged.

Hier ist, was mit arbeite ich:

public class BaseDependencyObject : DependencyObject, INotifyPropertyChanged
{
    public BaseDependencyObject()
    {

    }

    protected void SetValues(Object thisObject, Object entity)
    {
        try
        {
            PropertyInfo[] properties = entity.GetType().GetProperties();
            foreach (PropertyInfo property in properties)
            {
                var value = property.GetValue(entity, null);
                var valueIsEntity = value is System.ServiceModel.DomainServices.Client.Entity;
                var thisObjectsProperty = thisObject.GetType().GetProperty(property.Name);

                if (thisObjectsProperty != null && value != null)
                {
                    if (valueIsEntity)
                    {
                        if (thisObjectsProperty.PropertyType.GetInterface("INotifyPropertyChanged", true) != null)
                        {
                            var propertyInstance = Activator.CreateInstance(thisObjectsProperty.PropertyType);

                            ((INotifyPropertyChanged)propertyInstance).PropertyChanged += new PropertyChangedEventHandler(Object_PropertyChanged);
                        }

                        SetValues(thisObjectsProperty, value);
                    }

                    else if (thisObjectsProperty.PropertyType.GetInterface("ICollection", true) != null
                        && thisObjectsProperty.PropertyType.GetGenericArguments().Count() > 0)
                    {
                        Type genericType = thisObjectsProperty.PropertyType.GetGenericArguments()[0];

                        var observableCollection = Activator.CreateInstance(thisObjectsProperty.PropertyType) as IList;

                        if (observableCollection is INotifyCollectionChanged)
                            ((INotifyCollectionChanged)observableCollection).CollectionChanged += this.Object_CollectionChanged;

                        if (observableCollection is INotifyPropertyChanged)
                            ((INotifyPropertyChanged)observableCollection).PropertyChanged += new PropertyChangedEventHandler(Object_PropertyChanged);

                        foreach (var item in (IEnumerable)value)
                        {
                            var newItem = Activator.CreateInstance(genericType);

                            if (newItem != null)
                            {
                                SetValues(newItem, item);
                                observableCollection.Add(newItem);
                            }
                        }
                    }

                    else
                    {
                        thisObjectsProperty.SetValue(thisObject, value, null);

                    }
                }
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    protected void Object_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        switch (e.Action)
        {
            case NotifyCollectionChangedAction.Add:
                foreach (var item in e.NewItems)
                {
                    if (item is INotifyPropertyChanged)
                    {
                        ((INotifyPropertyChanged)item).PropertyChanged += new PropertyChangedEventHandler(Object_PropertyChanged);
                    }
                }
                break;

            case NotifyCollectionChangedAction.Remove:
                foreach (var item in e.OldItems)
                {
                    if (item is INotifyPropertyChanged)
                    {
                        ((INotifyPropertyChanged)item).PropertyChanged -= this.Object_PropertyChanged;
                    }
                }
                break;
        }

    }

    protected void Object_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        this.NotifyPropertyChanged(e.PropertyName);
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void NotifyPropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;

        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));

    }
}

Die erste param der SetValues ??Methode ist der DependencyObject-Typ, der in dem View-Modell verwendet wird. Der zweite param ist die Einheit, die aus dem Domainservice des Context.LoadOperation zurückgegeben wird.

Was meine Frage läuft darauf hinaus, wenn die INotifyCollectionChanged.CollectionChanged feuert ich um die Lage sein, das Property Ereignis zu erhöhen mit der Eigenschaftsnamen der Sammlung. Also, wenn jemand eine Beratung hat, würde ich es sehr schätzen. Vielen Dank im Voraus.

Bearbeiten
Herausgefunden, wie die Eigenschaften Namen zu erhalten, die das Ereignis feuert. Hier ist eine bearbeitete Version meiner PropertyChangedEventHandler.

protected void Object_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        var properties = this.GetType().GetProperties().Where(x => x.PropertyType == sender.GetType()).ToArray();

        foreach (var property in properties)
        {
            this.NotifyPropertyChanged(property.Name);
        }

        //this.NotifyPropertyChanged(e.PropertyName);
    }

Im Grunde ist dies tut, was ich suchte, aber aparentyly bin ich noch nicht etwas richtig machen. Die UIElement aktualisiert noch nicht, wenn die ObservableCollection, die eine Eigenschaft eines anderen Typs ist, hinzugefügt wird.

Hier ist ein Beispiel für meine DependencyObjects und Ansichtsmodell:

public class LOB : DependencyObject
{
    public Int32 ID
    {
        get { return (Int32)GetValue(IDProperty); }
        set
        {
            SetValue(IDProperty, value);
            NotifyPropertyChanged("ID");
        }
    }

    public static readonly DependencyProperty IDProperty =
    DependencyProperty.Register("ID", typeof(Int32), typeof(LOB), null);

    public ObservableCollection<Group> Groups
    {
        get { return (ObservableCollection<Group>)GetValue(GroupsProperty); }
        set
        {
            SetValue(GroupsProperty, value);
            NotifyPropertyChanged("Groups");
        }
    }

    public static readonly DependencyProperty GroupsProperty =
    DependencyProperty.Register("Groups", typeof(ObservableCollection<Group>), typeof(LOB), new PropertyMetadata(null, OnGroupsPropertyChanged));

    static void OnGroupsPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        if (e.NewValue != null)
        {
            ((INotifyCollectionChanged)e.NewValue).CollectionChanged += new NotifyCollectionChangedEventHandler(((LOB)obj).Object_CollectionChanged);
            ((INotifyPropertyChanged)e.NewValue).PropertyChanged += new PropertyChangedEventHandler(((LOB)obj).Object_PropertyChanged);
        }
        if (e.OldValue != null)
        {
            ((INotifyCollectionChanged)e.OldValue).CollectionChanged -= ((LOB)obj).Object_CollectionChanged;
            ((INotifyPropertyChanged)e.OldValue).PropertyChanged -= ((LOB)obj).Object_PropertyChanged;
        }
    }

}

public class Group : DependencyObject
{
    public Int32 ID
    {
        get { return (Int32)GetValue(IDProperty); }
        set
        {
            SetValue(IDProperty, value);
            NotifyPropertyChanged("ID");
        }
    }

    public static readonly DependencyProperty IDProperty =
    DependencyProperty.Register("ID", typeof(Int32), typeof(Group), null);

    public String GroupName
    {
        get { return (String)GetValue(GroupNameProperty); }
        set
        {
            SetValue(GroupNameProperty, value);
            NotifyPropertyChanged("GroupName");
        }
    }

    public static readonly DependencyProperty GroupNameProperty =
    DependencyProperty.Register("GroupName", typeof(String), typeof(Group), null);

}

public class MyViewModel : DependencyObject
{
    public static readonly DependencyProperty LobCollectionProperty =
        DependencyProperty.Register("LobCollection",
            typeof(ObservableCollection<LOB>),
            typeof(MyViewModel),
            new PropertyMetadata(null, LobCollectionPropertyChanged));

    public ObservableCollection<LOB> LobCollection
    {
        get { return (ObservableCollection<MainBusinessLine>)GetValue(LobCollectionPropertyChanged); }
        set
        {
            SetValue(MainBusinessLineCollectionProperty, value);
            NotifyPropertyChanged("LobCollection");
        }
    }

    static void LobCollectionPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        var viewModel = obj as MyViewModel;

        if (viewModel == null)
            return;

        if (e.OldValue != null)
        {
            ((INotifyCollectionChanged)e.OldValue).CollectionChanged -= viewModel.LobCollection_Changed;
        }

        if (e.NewValue != null)
        {
            ((INotifyCollectionChanged)e.NewValue).CollectionChanged += viewModel.LobCollection_Changed;
        }

    }

    void LobCollection_Changed(object sender, NotifyCollectionChangedEventArgs e)
    {
        NotifyPropertyChanged("LobCollection");
    }
}  
War es hilfreich?

Lösung

Nach unserem Gespräch über, dann ist dies eher strittig, aber ich dachte daran, wie ich eine Basisklasse implementieren würde, die Property Ereignisse ausgelöst, wenn eine Sammlung in einer Eigenschaft geändert, die von der Unterklasse definiert wurde. Wie gesagt, es ist ein bisschen Nicht-Standard, aber hier ist, wie ich es tun würde.

class FancyCollectionAndPropertyChangedBase : INotifyPropertyChanged
{
    private Dictionary<ICollectionChanged, String> collectionNameLookup = new Dictionary<ICollectionChanged, String>();

    protected FancyCollectionAndPropertyChangedBase()
    {
        this.PropertyChanged += MyPropertyChanged;
    }

    private void MyPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if(this.collectionNameLookup.ContainsValue(e.PropertyName)
        {
            KeyValuePair<INotifyCollectionChanged, String> oldValue = this.collectionNameLookup.First(kvp => kvp.Value == e.Name);
            oldValue.Key -= MyCollectionChanged;
            this.collecitonNameLookup.Remove(oldValue.Key);

            INotifyCollectionChanged collection = this.GetType().GetProperty(e.PropertyName, BindingFlags.FlattenHierarchy).GetValue(this, null);
            collection.CollectionChanged += MyCollectionChanged;
            this.collectionNameLookup.Add(collection, e.Name);
        }
        else if(typeof(INotifyCollectionChanged).IsAssignableFrom(this.GetType().GetProperty(e.PropertyName,  BindingFlags.FlattenHierarchy).PropertyType))
        {
            // Note: I may have gotten the IsAssignableFrom statement, above, backwards. 
            INotifyCollectionChanged collection = this.GetType().GetProperty(e.PropertyName, BindingFlags.FlattenHierarchy).GetValue(this, null);
            collection.CollectionChanged += MyCollectionChanged;
            this.collectionNameLookup.Add(collection, e.Name);
        }
    }

    private void MyCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        this.NotifyPropertyChanged(this.collectionNameLookup[sender];
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top