У меня есть класс, который выполняет потенциально длительную операцию, поэтому он сообщает о своем прогрессе, активируя событие, и я планирую запустить его в отдельном потоке из пользовательского интерфейса. Для того, чтобы проверить сообщение о событии статус будет обновлять 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
, и изменения не обнаруживаются зависимостью имущество. Но пока я не нашел упоминания о специальных шагах, которые необходимы, если свойство зависимостей является коллекцией.
Что я делаю неправильно?
Wow, большой улов! Благодаря! –
Это не лучший способ сделать это с точки зрения совместимости. Лучшим решением, вероятно, было бы сделать это типа ICollection и обработать событие CollectionChanged коллекции, чтобы поднять событие с измененным свойством. НО, для ваших нужд этого будет достаточно. –