Daniel Filipov
Daniel Filipov

Reputation: 325

How do i bind ListView Data with List using MVVM

I'm trying to bind List<> to ListView. When i'm updating i'm going to clear the list. Clear on ObservableCollection was kind of slow. Problem is that in the view things are not updated correctly.

XAML

<StackPanel.Resources>
    <ResourceDictionary>
        <common:BoolToBackgroundConverter x:Key="BoolToBackground"/>
        <tb:StringInlineCollectionConvertor x:Key="InlineConvert"/>
    </ResourceDictionary>
</StackPanel.Resources>
<ListView ItemsSource="{Binding NotificationsCollection, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}" 
            ScrollViewer.CanContentScroll="False">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel/>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
    <ListView.ItemTemplate>
        <DataTemplate>
            <Border>
                <Grid Background="{Binding NotSeen,Converter={StaticResource BoolToBackground},UpdateSourceTrigger=PropertyChanged,NotifyOnSourceUpdated=True}">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="auto"/>
                        <RowDefinition Height="*"/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                    </Grid.ColumnDefinitions>
                    <Image Source="{Binding Thumb}"/>
                    <tb:BindableTextBlock InlineCollection="{Binding Text, Converter={StaticResource InlineConvert}}"/>
                    <TextBlock Text="{Binding Created}"/>
                </Grid>
            </Border>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

C# ViewModel

public List<NotificationDataModel> notificationsCollection;
public List<NotificationDataModel> NotificationsCollection
{
    get
    {
        if (notificationsCollection == null)
        {
            notificationsCollection = new List<NotificationDataModel>();
        }
        return notificationsCollection;
    }
    set
    {
        if (notificationsCollection == null)
        {
            notificationsCollection = new List<NotificationDataModel>();
        }
        notificationsCollection.Clear();
        foreach (var item in value)
        {
            notificationsCollection.Add(item);
        }
        this.OnPropertyChanged("NotificationsCollection");
    }
}

public void UpdateNotifications1()
{
    List<NotificationDataModel> newCollection = new List<NotificationDataModel>();
    newCollection.Add(item1);
    newCollection.Add(item2);
    newCollection.Add(item3);
    newCollection.Add(item4);
    newCollection.Add(item5);
    newCollection.Add(item6);
    this.NotificationsCollection = newCollection;
}

public void UpdateNotifications2()
{
    List<NotificationDataModel> newCollection = new List<NotificationDataModel>();
    newCollection.Add(item1);
    newCollection.Add(item2);
    newCollection.Add(item6);
    this.NotificationsCollection = newCollection;
}

When i call UpdateNotifications1 elements are show accordingly but after that when i call UpdateNotifications2 i see item1, item2 and item3 instead of item6. Also items are getting new value for the NotSeen(black for example, and initial is white) property after closing the view and on reopening those items should have white but they are still with black background.

Upvotes: 1

Views: 3149

Answers (2)

Clemens
Clemens

Reputation: 128042

The problem is that raising the PropertyChanged event in your NotificationsCollection setter is ineffective when the actual value of the underlying field hasn't changed. The target ItemsSource property receives the same List instance (from the binding) and therefore does not trigger a UI update.

So do not clear and copy to an existing collection, but use the one passed to the setter instead:

public List<NotificationDataModel> NotificationsCollection
{
    get { return notificationsCollection; }
    set
    {
        notificationsCollection = value;
        OnPropertyChanged("NotificationsCollection");
    }
}

Upvotes: 1

Muds
Muds

Reputation: 4116

well either create a new list every time or use something like ObservableCollection<>

Upvotes: 0

Related Questions