WPF ObservableCollection
An ObservableCollection is a dynamic collection of objects of a given type. Objects can be added, removed or be updated with an automatic notification of actions. When an object is added to or removed from an observable collection, the UI is automatically updated. This happens because, when binding to an observable collection, WPF automatically adds a CollectionChanged event handler to the ObservableCollecion's events.
The ObservableCollection class exists in the System.Collections.ObjectModel namespace.
I will demonstrate how this works in a simple example:
I have a window with a Button, two TextBoxes and a ListView and each time you click the Button the text of the TextBox is added to the collection and the ListView is updated automatically.
UI
Code File
- public partial class MainWindow : Window
- {
- private ObservableCollection<Person> person;
- public MainWindow()
- {
- InitializeComponent();
- person = new ObservableCollection<Person>()
- {
- new Person(){Name="Prabhat",Address="India"},
-
- new Person(){Name="Smith",Address="US"}
- };
- lstNames.ItemsSource = person;
- }
- private void btnNames_Click(object sender, RoutedEventArgs e)
- {
- person.Add(new Person() { Name = txtName.Text, Address = txtAddress.Text });
- txtName.Text = string.Empty;
- txtAddress.Text = string.Empty;
- }
- }
-
- public class Person
- {
- public string Name { get; set; }
- public string Address { get; set; }
- }
Here a Person class has the 2 properties Name and Address. One observableCollection object is created with a Person type and bound to the ListView. See:
lstNames.ItemsSource = person;
By doing so, we can dynamically insert, update and remove items from the ListView, as in:
- person.Add(new Person() { Name = txtName.Text, Address = txtAddress.Text });
XAML File
- <Grid>
- <Grid.ColumnDefinitions>
- <ColumnDefinition/>
- <ColumnDefinition Width="*"/>
- </Grid.ColumnDefinitions>
- <Grid.RowDefinitions>
- <RowDefinition Height="*"></RowDefinition>
- </Grid.RowDefinitions>
- <StackPanel Grid.Row="0" Grid.Column="0" Margin="5,5,5,5">
- <TextBlock x:Name="lblName" Text="Name"></TextBlock>
- <TextBox x:Name="txtName"></TextBox>
- <TextBlock x:Name="lblAddress" Text="Address"></TextBlock>
- <TextBox x:Name="txtAddress"></TextBox>
- <Button Grid.Column="0" Width="100" Height="20" Margin="5,5,5,5" x:Name="btnNames" Click="btnNames_Click" Content="Add"></Button>
- </StackPanel>
- <ListView x:Name="lstNames" Margin="5,5,5,5" Grid.Column="1" Grid.Row="0">
- <ListView.View>
- <GridView x:Name="grdNames">
- <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>
- <GridViewColumn Header="Address" DisplayMemberBinding="{Binding Address}"/>
- </GridView>
- </ListView.View>
- </ListView>
- </Grid>
The ObservableCollection is already bound to the Listview. So all we need to do in the XAML file is to specify the binding member for each column. We can do that by the "DisplayMemberBinding" attribute and "Binding" markup extension. See:
- <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>