Tôi đã đọc tất cả các bài viết liên quan ở đây trong bảng nhưng tôi vẫn không thể giải quyết được vấn đề của mình mà tôi có khi liên kết ObservableCollection với ListView.Thay đổi trong ObservableCollection không cập nhật ListView
Tôi có lớp mô hình CLogEntry về cơ bản bao bọc một chuỗi.
/// Model of LogEntry
public class CLogEntry:INotifyPropertyChanged
{
/// Fields
private string _logEntry;
/// Property
public string LogEntry
{
get { return _logEntry; }
set
{
_logEntry = value;
RaisePropertyChanged("LogEntry");
}
}
/// PropertyChanged event handler
public event PropertyChangedEventHandler PropertyChanged;
/// Constructor
public CLogEntry(string logEntry)
{
this.LogEntry = logEntry;
}
/// Property changed Notification
public void RaisePropertyChanged(string propertyName)
{
// take a copy to prevent thread issues
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Trong ViewModel, tôi có một ObservableCollection chứa các đối tượng CLogEntry của tôi cũng như tài sản công cộng tương ứng cho nó.
class CLoggerViewModel : INotifyPropertyChanged
{
/// Memory Appender object
private CMemoryAppender _memoryAppender;
/// ObservableCollection for LogEntries
private ObservableCollection<CLogEntry> _logEntries;
/// Property to expose ObservableCollection for UI
public ObservableCollection<CLogEntry> LogEntries
{
get { return _logEntries; }
}
/// Event for PropertyChanged Notification
public event PropertyChangedEventHandler PropertyChanged;
/// Constructor of viewModel
public CLoggerViewModel()
{
this._logEntries = new ObservableCollection<CLogEntry>();
this._memoryAppender = new CMemoryAppender();
this._memoryAppender.PropertyChanged += new PropertyChangedEventHandler(OnMemoryAppenderPropertyChanged);
this._memoryAppender.LogContentChanged += new LoggingEventHandler(OnLogContentChanged);
}
/// Update collection
public void OnLogContentChanged(object sender, LoggingEventArgs e)
{
/// Here i add LogEntries event based to my collection.
/// For simplicity i just used a temporarly string here.
string[] tmpString = { "A", "B", "C", "D" };
foreach (string s in tmpString)
{
this.LogEntries.Add(new CLogEntry(s));
}
}
/// Any of the properties of the MemoryAppender objects has changed
private void OnMemoryAppenderPropertyChanged(object sender, PropertyChangedEventArgs e)
{
this.RaisePropertyChanged(e.PropertyName);
}
/// PropertyChanged EventHandler
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
mã XAML của tôi cho ListView như sau:
<ListView x:Name="lstLogs" DataContext ="{Binding LoggerViewModel}" ItemsSource="{Binding LogEntries}" Margin="5,5,5,5" Grid.Column="1" Grid.Row="0">
<ListView.View>
<GridView x:Name="grdLogs">
<GridViewColumn Header="Log Entry" DisplayMemberBinding="{Binding Path=LogEntries}"/>
</GridView>
</ListView.View>
</ListView>
Vấn đề của tôi là danh sách không hiển thị bất kỳ dữ liệu. Nhưng khi tôi gỡ lỗi mã tôi có thể thấy rằng thuộc tính của tôi cho ObservableCollection được gọi và bộ sưu tập của tôi chứa tất cả các LogEntries mà tôi thêm vào. Vì vậy, tôi cho rằng sự kiện CollectionChanged được kích hoạt và giao diện người dùng đang gọi thuộc tính LogEntries của tôi. Nhưng tôi không hiểu tại sao ListView không hiển thị bất kỳ dữ liệu nào.
Có vấn đề với mã XAML của tôi hay có vấn đề trong mô hình và/hoặc ViewModel không?
EDIT:
Cuối cùng vấn đề là một vấn đề luồng. Vì ObervableCollection được tạo bởi chuỗi giao diện người dùng, nó sẽ đưa ra một ngoại lệ nếu một luồng khác đang thêm/thao tác bộ sưu tập. Để loại bỏ vấn đề này, tôi tìm thấy giải pháp sau đây thực hiện một ObservableCollection không đồng bộ.
liên kết sau giúp tôi để có được nó làm việc: Stackoverflow Implementing Async ObservableCollection
Làm thế nào bạn thiết lập 'DataContext'? Và khi bạn khởi tạo thuộc tính 'LogEntries'? – har07
hãy sử dụng Snoop để kiểm tra DataContext và Binding Expression của bạn tại thời điểm chạy – blindmeis
@blindemeis: Spoof đang cho tôi biết: DataContext - [Logger.CLoggerViewModel] {Path = LoggerViewModel}. Nhưng đối với BindingExpression im không chắc chắn. tôi chỉ tìm thấy Properties cho Binding.XmlNamespaceManager và BindingGroup cho ListView trong Spoof. Nhưng cả hai thuộc tính không giữ bất kỳ giá trị trong thời gian chạy. – ck84vi