none
ListView.ItemsSource: howto update the UI whenever the source is updated?

    Question

  • Hi,

    I've got the following ListView:

    Code Snippet

    <ListView Name="lstCalendars" ScrollViewer.VerticalScrollBarVisibility="Visible" MouseDoubleClick="lstCalendars_MouseDoubleClick">
                    <ListView.View>
                        <GridView>                   
                            <!-- Title Column -->
                            <GridViewColumn>
                                <GridViewColumn.HeaderTemplate>
                                    <DataTemplate>
                                        <Label Content="Calendar" Margin="2,0" HorizontalAlignment="Left"/>
                                    </DataTemplate>
                                </GridViewColumn.HeaderTemplate>
                                <GridViewColumn.CellTemplate>
                                    <DataTemplate>
                                        <Label Content="{Binding Path=Title}" HorizontalAlignment="Left">
                                            <Label.Style>
                                                <Style>
                                                    <Style.Triggers>
                                                        <DataTrigger Binding="{Binding Path=Sync}" Value="True">
                                                            <Setter Property="Label.FontWeight" Value="Bold"/>
                                                        </DataTrigger>
                                                    </Style.Triggers>
                                                </Style>
                                            </Label.Style>
                                        </Label>
                                    </DataTemplate>
                                </GridViewColumn.CellTemplate>
                            </GridViewColumn>
                           
                            <!-- Owner Column -->
                            <GridViewColumn>
                                <GridViewColumn.HeaderTemplate>
                                    <DataTemplate>
                                        <Label Content="Owner" Margin="2,0" HorizontalAlignment="Left"/>
                                    </DataTemplate>
                                </GridViewColumn.HeaderTemplate>
                                <GridViewColumn.CellTemplate>
                                    <DataTemplate>
                                        <Label Content=""/>
                                    </DataTemplate>
                                </GridViewColumn.CellTemplate>
                            </GridViewColumn>

                            <!-- Synchronize Column -->
                            <GridViewColumn>
                                <GridViewColumn.HeaderTemplate>
                                    <DataTemplate>
                                        <Label Content="Synchronize" Margin="2,0"/>
                                    </DataTemplate>
                                </GridViewColumn.HeaderTemplate>
                                <GridViewColumn.CellTemplate>
                                    <DataTemplate>
                                        <CheckBox IsChecked="{Binding Path=Sync}" HorizontalAlignment="Center" HorizontalContentAlignment="Center"/>
                                    </DataTemplate>                       
                                </GridViewColumn.CellTemplate>
                            </GridViewColumn>
                           
                            <!-- Last Sync Column -->
                            <GridViewColumn>
                                <GridViewColumn.HeaderTemplate>
                                    <DataTemplate>
                                        <Label Content="Last Sync" Margin="2,0" HorizontalAlignment="Left"/>
                                    </DataTemplate>
                                </GridViewColumn.HeaderTemplate>
                                <GridViewColumn.CellTemplate>
                                    <DataTemplate>
                                        <Label Content="" HorizontalAlignment="Left"/>
                                    </DataTemplate>
                                </GridViewColumn.CellTemplate>
                            </GridViewColumn>
                           
                        </GridView>
                    </ListView.View>
                </ListView>


    I've got a List<HybridCalendar> calendars which I assign to the ItemsSource property of lstCalendars.
    This works great but the UI isn't automatically updated when the list is updated.

    For example, consider the following event handler:

    Code Snippet

    private void lstCalendars_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        if (this.lstCalendars.SelectedItems.Count > 0)
        {
            HybridCalendar calendar = (HybridCalendar)this.lstCalendars.SelectedItem;
            calendar.Sync = !calendar.Sync;
        }
    }


    This effectively updates the list, but not the UI.
    I could of course add this to the code:

    this.lstCalendars.Items.Refresh();

    But I'm guessing this is not the correct approach. I'd have to add this lots of times and it triggers a UI update
    for all the items in the list, which isn't something I'd want if the list became really long.

    Any suggestions?
    Tuesday, March 11, 2008 9:33 AM

Answers

  • This is because the List<T> class does not implement the INotifyCollectionChanged interface. The solution would be use either ObservableCollection<T> or your own Type that inherits from it (You could also create your own type and fully implement INotifyCollectionChanged, but this is rarely necessary).

     

     Note that one of the ObservableCollection<T> constructors takes a Generic List as a parameter and constructs its own inner list from it, so you could simply insantiate a new ObservableCollection(Of HybridCalendar)(yourList) and then set the ListView's ItemsSource to it. This should give you the immediate UI Update functionality you are looking for.

     

    Hope this helps,

     

    Keith

     

    Tuesday, March 11, 2008 12:52 PM

All replies

  • This is because the List<T> class does not implement the INotifyCollectionChanged interface. The solution would be use either ObservableCollection<T> or your own Type that inherits from it (You could also create your own type and fully implement INotifyCollectionChanged, but this is rarely necessary).

     

     Note that one of the ObservableCollection<T> constructors takes a Generic List as a parameter and constructs its own inner list from it, so you could simply insantiate a new ObservableCollection(Of HybridCalendar)(yourList) and then set the ListView's ItemsSource to it. This should give you the immediate UI Update functionality you are looking for.

     

    Hope this helps,

     

    Keith

     

    Tuesday, March 11, 2008 12:52 PM
  • I'm now using
    private ObservableCollection<HybridCalendar> calendars;

    But I still have to call Items.Refresh() manually in order for UI changes to be visible... I'm missing something....
    Tuesday, March 11, 2008 1:26 PM