結論から言うと Dispatcher する。
INotifyPropertyChanged を実装したクラスがあるとして
public class hoge : INotifyPropertyChanged { private string _name; public string name { get { return _name; } set { _name = value; NotifyPropertyChanged("name"); } } #region 通知 public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } #endregion }
ObservableCollection<hoge> なリストのクラスを作る。ビューモデル的な。
public class HogeList : INotifyPropertyChanged { ObservableCollection<hoge> _hoges; public ObservableCollection<hoge> Hoges { get { return _hoges; } } public void AddHoge(hoge value) { _hoges.Add(value); NotifyPropertyChanged("Hoges"); } #region 通知 public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } #endregion }
GridView / ListView にバインド。
var hoge = new HogeList(); this.DataContext = hoge.Hoges;
非同期的なタイミング(自分の場合、TCPの受信)で列を追加。
void _listener_ConnectionReceived(Windows.Networking.Sockets.StreamSocketListener sender, Windows.Networking.Sockets.StreamSocketListenerConnectionReceivedEventArgs args) { // データ受信的な処理 hoge.AddHoge(受信データ); }
で、実行したらリストクラスの PropertyChanged でエラーになった。
型 'System.Runtime.InteropServices.COMException' の例外が System.dll で発生しましたが、ユーザー コード内ではハンドルされませんでした 追加情報:アプリケーションは、別のスレッドにマーシャリングされたインターフェイスを呼び出しました。 (HRESULT からの例外:0x8001010E (RPC_E_WRONG_THREAD))
UIにバインドしているので、スレッドセーフな動作にしておく必要があるのかな?
こちらの記事を参考にして解決。
受信時の処理に Dispatcher.RunAsync を差し込む。
void _listener_ConnectionReceived(Windows.Networking.Sockets.StreamSocketListener sender, Windows.Networking.Sockets.StreamSocketListenerConnectionReceivedEventArgs args) { // データ受信的な処理 await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, delegate { hoge.AddHoge(受信データ); }); }
一応これで解決。