BJladu4
BJladu4

Reputation: 273

How to update ListBox when ObservableCollection items changed?

I have test app which adding items to ListBox in loop. Now, ListBox updates, when all items added to ObservableCollection. I need to update ListBox when every item added. Please, help russian guy =)

Here is my code:

MainWindow.xaml

<Grid>
    <Button Content="Button" HorizontalAlignment="Left" Margin="432,288.04,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
    <ListBox x:Name="urlsListBox" ItemsSource="{Binding Urls}" HorizontalAlignment="Left" Height="300" Margin="10,10,0,0" VerticalAlignment="Top" Width="417"/>
</Grid>

MainWindow.xaml.cs

/// <summary>
/// Логика взаимодействия для MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    ViewModel model = new ViewModel();

    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = model;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        model.GetUrls();
    }
}

ViewModel.cs

class ViewModel
{
    public ObservableCollection<Url> Urls { get; set; }

    public ViewModel()
    {
        Urls = new ObservableCollection<Url>();
    }

    public void GetUrls()
    {
        for (int i = 0; i < 5; i++)
        {
            Urls.Add(new Url { link = i.ToString() });
            //Thread.Sleep(300);
        }
    }
}

public class Url
{
    public string link { get; set; }
}

Upvotes: 1

Views: 1337

Answers (2)

Rishi_raj
Rishi_raj

Reputation: 85

I think you need to notify the UI about the change happening in the URL observable collection each time it adds a new item.

If you have implemented INotifyPropertyChanged in your view model then register the observable collection with any change happening in it.

private ObservableCollection<Url> _urls; 
public ObservableCollection<Url> Urls 
{ get
  { 
    return _urls;
  } 
  set
  {
    _urls = value;
    OnPropertyModified("Urls");
  }
}

Upvotes: 1

Rohit Vats
Rohit Vats

Reputation: 81253

You want UI to update on every item addition in collection i guess.

Looking at Thread.Sleep(300), i am assuming you want to wait for 300 milliseconds before adding another item to collection.

DispatcherTimer is what you are looking for then. This sample will work:

public void GetUrls()
{
    DispatcherTimer timer = new DispatcherTimer();
    timer.Interval = new TimeSpan(0, 0, 0, 0, 300);
    int i = 0;
    timer.Tick += (s, e) =>
       {
           Urls.Add(new Url { link = i.ToString() });
           ++i;
           if (i == 5)
             timer.Stop();
       };
    timer.Start();
}

This will add item in collection after every 300 ms and will stop timer once item count reaches to 5.


Like i mentioned in comment

Dispatcher associated with UI thread can process one operation at a time. When it's adding item to collection, it can't process Rendering operation at same time. Hence GUI not getting refreshed. Usage of DispatcherTimer gives some time to rendering operations to get processed.

Another approach without DispatcherTimer would be to enqueue empty delegate on UI dispatcher with Render priority so that all operations with priority higher than Render (including Render) gets processed before moving to addition of another item in collection.

public void GetUrls()
{
    for (int i = 0; i < 5; i++)
    {
        Urls.Add(new Url { link = i.ToString() });
        App.Current.Dispatcher.Invoke((Action)(() => { }),
                                               DispatcherPriority.Render);
    }
}

Upvotes: 0

Related Questions