简体   繁体   中英

Bind ListView to ObservableCollection and Linq

Hi Im trying to bind a ListView to a Linq, and make it react on changes in the collection.

public partial class MainWindow
{
    readonly ObservableCollection<Person> _persons = new ObservableCollection<Person>();
    readonly Team _team1 = new Team { Name = "Team 1" };
    readonly Team _team2 = new Team { Name = "Team 2" };
    readonly Team _team3 = new Team { Name = "Team 3" };

    public MainWindow()
    {
        InitializeComponent();

        _persons.Add(new Person {Name = "James", Team = _team1});
        _persons.Add(new Person {Name = "John", Team = _team2});
        _persons.Add(new Person {Name = "Peter", Team = _team3});
        _persons.Add(new Person {Name = "Jack", Team = _team1});
        _persons.Add(new Person {Name = "Jones", Team = _team2});
        _persons.Add(new Person {Name = "Bauer", Team = _team3});
        _persons.Add(new Person {Name = "Bo", Team = _team1});
        _persons.Add(new Person {Name = "Ben", Team = _team2});
        _persons.Add(new Person {Name = "Henry", Team = _team3});

        TeamList1.ItemsSource = from person in _persons where person.Team == _team1 select person;
        TeamList2.ItemsSource = from person in _persons where person.Team == _team2 select person;
        TeamList3.ItemsSource = from person in _persons where person.Team == _team3 select person;
    }

    private void ButtonClick(object sender, RoutedEventArgs e)
    {
        _persons[0].Team = _team2;
    }
}

And my Models

 public class Person : INotifyPropertyChanged
    {
        private string _name;
        public String Name
        {
            get { return _name; }
            set { _name = value; NotifyPropertyChanged("Name"); }
        }

        private Team _team;
        public Team Team
        {
            get { return _team; }
            set { _team = value; NotifyPropertyChanged("Team"); }
        }

        public override string ToString()
        {
            return string.Format("Name {0}\t{1}", Name, Team);
        }
        public event PropertyChangedEventHandler PropertyChanged;

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

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

        public override string ToString()
        {
            return Name;
        }
        public event PropertyChangedEventHandler PropertyChanged;

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

And the Xaml

<Grid>
        <StackPanel Orientation="Vertical">
        <StackPanel>
            <ListView Name="TeamList1"/>
            <ListView Name="TeamList2"/>
            <ListView Name="TeamList3"/>
        </StackPanel>
            <Button Content="Click Me" Click="ButtonClick"/>
        </StackPanel>
    </Grid>

When the ButtonClick is called I would like my ListView to reflect the changes it made on the _persons.

Just don't use linq, there are CollectionViews for this sort of thing which have filters, you then only have to refresh the views (See: How to: Filter data in a view ). (If you must use linq there are also bindable extensions to it)

The LINQ query is evaluated when it is bound to the data source and the items in the list view are generated. The LINQ query will not be re-evaluated whenever you change the properties of a person inside the original list _persons . To achieve this, you have to do a custom implementation that listens to the PropertyChanged event of each Person in the original list and updates an ObservableCollection<Person> accordingly. This observable collection you would bind to the list view.

You need my ObservableComputations library. Using this library you can code like this:

    TeamList1.ItemsSource = _persons.Filtering(person.Team == _team1);
    TeamList2.ItemsSource = _persons.Filtering(person.Team == _team2);
    TeamList3.ItemsSource = _persons.Filtering(person.Team == _team3);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM