2015-08-06 2 views
0

У меня есть класс, который выполняет потенциально длительную операцию, поэтому он сообщает о своем прогрессе, активируя событие, и я планирую запустить его в отдельном потоке из пользовательского интерфейса. Для того, чтобы проверить сообщение о событии статус будет обновлять DataBound ListBox, как и планировалось, я сделал фиктивный класс с тем же типом события:Диспетчер обновляет UI в первый раз, когда он называется

class NoisyComponent 
{ 
    public EventHandler<string> OnProgress; 
    protected void prog(params string[] msg) 
    { 
     if (OnProgress != null) 
      OnProgress(this, string.Join(" ", msg)); 
    } 

    public void Start(int lim) 
    { 
     for (int i = 0; i < lim; i++) 
     { 
      prog("blah blah blah", i.ToString()); 
      System.Threading.Thread.Sleep(200); 
     } 
    } 
} 

страница Я тестирую его имеет ListBox:

<ListBox ItemsSource="{Binding Path=appstate.progress_messages, Source={x:Static Application.Current}}"></ListBox> 

И я начинаю задачу в OnRender:

protected override void OnRender(DrawingContext drawingContext) 
    { 
     base.OnRender(drawingContext); 

     var noisy = new NoisyComponent(); 
     noisy.OnProgress += (sender, msg) => 
     { 
      Dispatcher.Invoke(() => 
      { 
       (App.Current as App).appstate.progress_messages.Add(msg); 
       UpdateLayout(); 
      }); 
     }; 
     Task.Run(() => { noisy.Start(5); }); 
    } 

appstate.progress_messages свойство зависимостей

public List<string> progress_messages 
    { 
     get { return (List<string>)GetValue(progress_messagesProperty); } 
     set { SetValue(progress_messagesProperty, value); } 
    } 
    public static readonly DependencyProperty progress_messagesProperty = 
     DependencyProperty.Register("progress_messages", typeof(List<string>), typeof(AppState), new PropertyMetadata(new List<string>())); 

Я ожидал увидеть новую строку «blah blah blah #» в списке каждые 200 мс, но вместо этого я просто вижу первый («blah blah blah 0») и ничего больше. Я установил точку останова внутри лямбда Dispatcher.Invoke, и она определенно запускается несколько раз, и свойство обновляется, но это просто не отображается в пользовательском интерфейсе.

Я думал, что проблема может заключаться в том, что, поскольку свойство представляет собой список, ему присваивается только один раз, а затем на существующий объект вызывается метод Add, и изменения не обнаруживаются зависимостью имущество. Но пока я не нашел упоминания о специальных шагах, которые необходимы, если свойство зависимостей является коллекцией.

Что я делаю неправильно?

ответ

1

Я не уверен, но ...

попробовать сделать progress_messages ObservableCollection Согласовать

public ObservableCollection<string> progress_messages 
    { 
     get { return (ObservableCollection<string>)GetValue(progress_messagesProperty); } 
     set { SetValue(progress_messagesProperty, value); } 
    } 
    public static readonly DependencyProperty progress_messagesProperty = 
     DependencyProperty.Register("progress_messages", typeof(ObservableCollection<string>), typeof(AppState), new PropertyMetadata(new ObservableCollection<string>())); 
+0

Wow, большой улов! Благодаря! –

+0

Это не лучший способ сделать это с точки зрения совместимости. Лучшим решением, вероятно, было бы сделать это типа ICollection и обработать событие CollectionChanged коллекции, чтобы поднять событие с измененным свойством. НО, для ваших нужд этого будет достаточно. –

Смежные вопросы