ObservableCollection
уже вызывает событие PropertyChanged при его изменении.Вам также не нужно вызывать событие в потоке пользовательского интерфейса.
Ваша модель может быть такой простой, как:
class LogModel
{
public ObservableCollection<string> Logging { get; } = new ObservableCollection<string>();
public void Add(string text)
{
Logging.Add(text);
}
}
Все, что вам нужно сделать, это установить DataContext
вашего взгляда, например:
LogModel model = new LogModel();
public MainWindow()
{
InitializeComponent();
this.DataContext = model;
}
Я предполагаю, что StartTest
- это обработчик кликов, который означает, что он работает в потоке пользовательского интерфейса.Это означает, что он будет блокировать поток пользовательского интерфейса до завершения цикла.После завершения цикла пользовательский интерфейс будет обновлен.
Если вы хотите, чтобы пользовательский интерфейс оставался отзывчивым во время цикла, используйте Task.Delay
вместо Thread.Slepp, например:
private async void Button_Click(object sender, RoutedEventArgs e)
{
for(int i=0;i<10;i++)
{
await Task.Delay(100);
model.Add("Blah!");
}
}
Обновление
Вам не нужно использовать ObservableCollection
в качестве источника привязки данных.Вы можете использовать любой объект, включая массив или список.В этом случае вы должны вызвать событие PropertyChanged в коде:
class LogModel:INotifyPropertyChanged
{
public List<string> Logging { get; } = new List<string>();
public event PropertyChangedEventHandler PropertyChanged;
public void Add(string text)
{
Logging.Add(text);
PropertyChanged.Invoke(this,new PropertyChangedEventArgs("Logging"));
}
}
. Это скажет представлению загрузить все содержимого и снова отобразить его.Это прекрасно, когда вы хотите отображать только данные, загруженные, например, из базы данных, без их изменения, поскольку это значительно упрощает сопоставление сущностей с ViewModels.В этом случае вам нужно обновлять представление только тогда, когда новая ViewModel присоединяется в результате выполнения команды.
Это не эффективно, хотя вам нужно обновить объединение.ObservableCollection реализует интерфейс INotifyCollectionChanged, который вызывает событие для каждого изменения.Если вы добавляете новый элемент, будет отображаться только этот элемент.
С другой стороны, следует избегать изменения коллекции в тесных циклах, поскольку она вызовет несколько событий.Если вы загрузите 50 новых предметов, не звоните Add
50 раз подряд.Создайте новую ObservableCollection, замените старую и вызовите событие PropertyChanged, например:
class LogModel:INotifyPropertyChanged
{
public ObservableCollection<string> Logging { get; set; } = new ObservableCollection<string>();
public event PropertyChangedEventHandler PropertyChanged;
public void Add(string text)
{
Logging.Add(text);
PropertyChanged.Invoke(this,new PropertyChangedEventArgs("Logging"));
}
public void BulkLoad(string[] texts)
{
Logging = new ObservableCollection<string>(texts);
PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Logging"));
}
}
Явная реализация по-прежнему необходима, поскольку свойство Logging
заменяется и не может вызывать какие-либо события самостоятельно