0

I have list which loading some long loading date. I can not use ObservableCollection because it can not be updated from another thread. What i need to do, because when I am using list nothing happens on UI * *

public class ListViewModel : ViewModelBase
{
    /// <summary>
    /// Initializes a new instance of the ListViewModel class.
    /// </summary>
    /// 
    private List<StructOfList> items;

    public List<StructOfList> Items 
    {
        get { return items; }
        set
        {
            items = value; 
            RaisePropertyChanged("Items");
        }
    }

    public ListViewModel()
    {
        Items = new List<StructOfList>();
        Items.Add(new StructOfList { Amount = 10, FirstName = "Test", SecondName = "Test" });
        AsyncDataLoad();
    }

    public void AsyncDataLoad()
    {
        Action<List<StructOfList>> LoadData = new Action<List<StructOfList>>(AddItemToList);
        IAsyncResult result = LoadData.BeginInvoke(Items, null, null);
    }

    public void AddItemToList(List<StructOfList> items)
    {
        for (int i = 0; i < 10; i++)
        {
            System.Threading.Thread.Sleep(300);
            items.Add(new StructOfList {FirstName = "First" , SecondName = "Second" , Amount = i});
            RaisePropertyChanged("Items");
        }
    }
}

Xaml code goes gere

<Grid>
    <ListView ItemsSource="{Binding Items}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition></ColumnDefinition>
                        <ColumnDefinition></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <Label Content="{Binding FirstName}" Grid.Column="0"></Label>
                    <Label Content="{Binding SecondName}" Grid.Column="1"></Label>
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>
A191919
  • 3,422
  • 7
  • 49
  • 93
  • [This answer](http://stackoverflow.com/a/18816823/1136211) may be helpful. – Clemens Jul 24 '15 at 15:28
  • Do your long operation, then update the UI on the UI thread. The UI can't observe a List, hence nothing works. Calling `RaisePropertyChange("Items")` won't help as the `ListView` will see the object hasn't actually changed and ignore it. – Charles Mager Jul 24 '15 at 15:44

2 Answers2

3

You can use an ObservableCollection as long as the update happens on the UI thread. Since all you have is an async function doing only non-conflicting transactions such as sequential adding, there should be no problem using Dispatcher to apply changes as they happen to the ObservableCollection:

public void AddItemToList()
{
    for (int i = 0; i < 10; i++)
    {
        System.Threading.Thread.Sleep(300);

        var AddItem = new Action(() => items.Add(new StructOfList { FirstName = "First", SecondName = "Second", Amount = i });
        Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, AddItem);
    }
}
Vlad
  • 1,889
  • 17
  • 33
0

A few things:

You do not need to have RaisePropertyChanged on your Items property since the Items object only gets updated once (in the CTOR).

You should be using async/await to perform the async data load.

You should also be using an OverservableCollection since your list will be updating items.

For example:

public class ListViewModel : ViewModelBase
{
    public ObservableCollection<StructOfList> Items 
    {
        get; private set;
    }

    public ListViewModel()
    {
        Items = new ObservableCollection<StructOfList>();
        Items.Add(new StructOfList { Amount = 10, FirstName = "Test", SecondName = "Test" });
        AsyncDataLoad();
    }

    public void async AsyncDataLoad()
    {
        await Task.Run(()=> AddItemsToList());
    }

    public void AddItemsToList()
    {
        for (int i = 0; i < 10; i++)
        {
            Application.Current.Dispatcher.Invoke(() => Items.Add(new StructOfList {FirstName = "First" , SecondName = "Second" , Amount = i}));
        }
    }
}
d.moncada
  • 16,900
  • 5
  • 53
  • 82