Объект привязки данных Winforms, содержащий список <T> - PullRequest
2 голосов
/ 13 июля 2009

У меня проблемы с ситуацией, которая, как я знаю, должна быть довольно распространенной, поэтому я надеюсь, что решение простое. У меня есть объект, который содержит список <> объектов. Он также имеет некоторые свойства, которые отражают совокупные данные об объектах в List <> (на самом деле это BindingList <>, поэтому я могу связываться с ним). В моей форме у меня есть DataGridView для списка и некоторые другие поля для совокупных данных. Я не могу понять, как вызвать обновление совокупных данных при изменении значений в DataGridView.

Я пытался вызвать событие PropertyChanged, когда свойства объектов в Списке изменены, но, похоже, это не обновляет отображение агрегированных данных. Если я получаю доступ к статистическому свойству (например, отображаю его в окне сообщения), текстовое поле в главной форме обновляется.

Вот несколько упрощенных кодов, иллюстрирующих то, что я пытаюсь сделать:

namespace WindowsFormsApplication1 {
public class Person {

    public int Age {
        get;
        set;
    }

    public String Name {
        get;
        set;
    }
}

public class Roster : INotifyPropertyChanged {

    public BindingList<Person> People {
        get;
        set;
    }

    public Roster () {
        People = new BindingList<Person>();
    }

    private int totalage;
    public int TotalAge {
        get {
            calcAges();
            return totalage;
        }
        set {
            totalage = value;
            NotifyPropertyChanged("TotalAge");
        }
    }

    private void calcAges () {
        int total = 0;
        foreach ( Person p in People ) {
            total += p.Age;
        }
        TotalAge = total;
    }

    #region INotifyPropertyChanged Members
    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged ( String info ) {
        if ( PropertyChanged != null ) {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
    #endregion
}
}

Ответы [ 2 ]

3 голосов
/ 13 июля 2009

Метод calcAges и свойство TotalAge выглядят очень подозрительно.

Во-первых, TotalAge должен быть доступен только для чтения. Если вы позволяете ему быть открытым и доступным для записи, какова логика изменения компонентов, составляющих возраст?

Во-вторых, каждый раз, когда вы получаете значение, вы запускаете событие PropertyChanged, что нехорошо.

Ваш класс Roster должен выглядеть следующим образом:

public class Roster : INotifyPropertyChanged {

    public Roster ()
    {
        // Set the binding list, this triggers the appropriate
        // event binding which would be gotten if the BindingList
        // was set on assignment.
        People = new BindingList<Person>();
    }

    // The list of people.
    BindingList<Person> people = null;

    public BindingList<Person> People 
    {
        get 
        { 
            return people; 
        }
        set 
        { 
            // If there is a list, then remove the delegate.
            if (people != null)
            {
                // Remove the delegate.
                people.ListChanged -= OnListChanged;
            }

            /* Perform error check here */ 
            people = value;

            // Bind to the ListChangedEvent.
            // Use lambda syntax if LINQ is available.
            people.ListChanged += OnListChanged;

            // Technically, the People property changed, so that
            // property changed event should be fired.
            NotifyPropertyChanged("People");

            // Calculate the total age now, since the 
            // whole list was reassigned.
            CalculateTotalAge();
        }
    }

    private void OnListChanged(object sender, ListChangedEventArgs e)
    {
        // Just calculate the total age.
        CalculateTotalAge();
    }

    private void CalculateTotalAge()
    {
        // Store the old total age.
        int oldTotalAge = totalage;

        // If you can use LINQ, change this to:
        // totalage = people.Sum(p => p.Age);

        // Set the total age to 0.
        totalage = 0;

        // Sum.
        foreach (Person p in People) {
            totalage += p.Age;
        }

        // If the total age has changed, then fire the event.
        if (totalage != oldTotalAge)
        {
            // Fire the property notify changed event.
            NotifyPropertyChanged("TotalAge");
        }
    }

    private int totalage = 0;

    public int TotalAge 
    {
        get 
        {
            return totalage;
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;

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

Теперь, когда свойства в элементах списка изменены, родительский объект вызовет событие изменения свойства, и все, что с ним связано, также должно измениться.

0 голосов
/ 13 июля 2009

Я полагаю, вы можете искать что-то вроде этого

ITypedList

Также Поиск Google ITypedList ведет вас к нескольким хорошим блогам о том, как реализовать.

Когда я использую ORM, мне обычно приходится делать несколько из них для удобного связывания и представления сетки данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...