<Window x:Class="WpfApplication1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApplication1" xmlns:sys="clr-namespace:System;assembly=mscorlib" Title="ListBinding" Height="325" Width="400"> <Window.Resources> <ObjectDataProvider x:Key="Family" ObjectType="{x:Type local:RemoteEmployeesLoader}" IsAsynchronous="True" MethodName="LoadEmployees"> <ObjectDataProvider.MethodParameters> <sys:String>http://host/d.dat</sys:String> <sys:String>http://host/d2.dat</sys:String> </ObjectDataProvider.MethodParameters> </ObjectDataProvider> <local:AgeToForegroundConverter x:Key="ageConverter" /> <DataTemplate DataType="{x:Type local:Employee}"> <TextBlock> <TextBlock Text="{Binding Path=Name}" /> (age: <TextBlock Text="{Binding Path=Age}" Foreground="{Binding Path=Age, Converter={StaticResource ageConverter}}" />) </TextBlock> </DataTemplate> </Window.Resources> <StackPanel DataContext="{StaticResource Family}"> <ListBox ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True"> <ListBox.GroupStyle> <x:Static Member="GroupStyle.Default" /> </ListBox.GroupStyle> </ListBox> <TextBlock>Name:</TextBlock> <TextBox Text="{Binding Path=Name}" /> <TextBlock>Age:</TextBlock> <TextBox Text="{Binding Path=Age}" Foreground="{Binding Path=Age, Converter={StaticResource ageConverter}}" /> <Button Name="birthdayButton">Birthday</Button> <Button Name="backButton">&lt;</Button> <Button Name="forwardButton">&gt;</Button> <Button Name="addButton">Add</Button> <Button Name="sortButton">Sort</Button> <Button Name="filterButton">Filter</Button> <Button Name="groupButton">Group</Button> </StackPanel> </Window> //File:Window.xaml.cs using System; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; using System.Collections.Generic; using System.Diagnostics; using System.ComponentModel; using System.Collections.ObjectModel; using System.Collections; namespace WpfApplication1 { public class Employee : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected void Notify(string propName) { if( this.PropertyChanged != null ) { PropertyChanged(this, new PropertyChangedEventArgs(propName)); } } string name; public string Name { get { return this.name; } set { this.name = value; Notify("Name"); } } int age; public int Age { get { return this.age; } set { this.age = value; Notify("Age"); } } public Employee() { } public Employee(string name, int age) { this.name = name; this.age = age; } } public class Employees : ObservableCollection<Employee> { } public class RemoteEmployeesLoader { public Employees LoadEmployees(string url1, string url2) { Employees employees = new Employees(); employees.Add(new Employee("A", 31)); employees.Add(new Employee("B", 42)); employees.Add(new Employee("C", 68)); return employees; } } public partial class Window1 : Window { public Window1() { InitializeComponent(); this.birthdayButton.Click += birthdayButton_Click; this.backButton.Click += backButton_Click; this.forwardButton.Click += forwardButton_Click; this.addButton.Click += addButton_Click; this.sortButton.Click += sortButton_Click; this.filterButton.Click += filterButton_Click; this.groupButton.Click += groupButton_Click; } ICollectionView GetFamilyView() { DataSourceProvider provider = (DataSourceProvider)this.FindResource("Family"); Employees employees = (Employees)provider.Data; return CollectionViewSource.GetDefaultView(employees); } void birthdayButton_Click(object sender, RoutedEventArgs e) { ICollectionView view = GetFamilyView(); Employee person = (Employee)view.CurrentItem; ++person.Age; Console.WriteLine(person.Name); Console.WriteLine(person.Age); } void backButton_Click(object sender, RoutedEventArgs e) { ICollectionView view = GetFamilyView(); view.MoveCurrentToPrevious(); if( view.IsCurrentBeforeFirst ) { view.MoveCurrentToFirst(); } } void forwardButton_Click(object sender, RoutedEventArgs e) { ICollectionView view = GetFamilyView(); view.MoveCurrentToNext(); if( view.IsCurrentAfterLast ) { view.MoveCurrentToLast(); } } void addButton_Click(object sender, RoutedEventArgs e) { DataSourceProvider provider = (DataSourceProvider)this.FindResource("Family"); Employees employees = (Employees)provider.Data; employees.Add(new Employee("EE", 67)); } class EmployeeSorter : IComparer { public int Compare(object x, object y) { Employee lhs = (Employee)x; Employee rhs = (Employee)y; int nameCompare = lhs.Name.CompareTo(rhs.Name); if( nameCompare != 0 ) return nameCompare; return rhs.Age - lhs.Age; } } void sortButton_Click(object sender, RoutedEventArgs e) { ListCollectionView view = (ListCollectionView)GetFamilyView(); if( view.CustomSort == null ) { view.CustomSort = new EmployeeSorter(); } else { view.CustomSort = null; } } void filterButton_Click(object sender, RoutedEventArgs e) { ICollectionView view = GetFamilyView(); if( view.Filter == null ) { view.Filter = delegate(object item) { return ((Employee)item).Age >= 25; }; } else { view.Filter = null; } } void groupButton_Click(object sender, RoutedEventArgs e) { ICollectionView view = GetFamilyView(); if( view.GroupDescriptions.Count == 0 ) { view.GroupDescriptions.Add(new PropertyGroupDescription("Age")); } else { view.GroupDescriptions.Clear(); } } } public class AgeToForegroundConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { Debug.Assert(targetType == typeof(Brush)); int age = int.Parse(value.ToString()); return (age > 25 ? Brushes.Red : Brushes.Black); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } }