ItemsSourceを取得してバインドを更新する方法は?
質問
GetAll()にバインドされているリストボックスを表示するビューがあります:
<DockPanel>
<ListBox ItemsSource="{Binding GetAll}"
ItemTemplate="{StaticResource allCustomersDataTemplate}"
Style="{StaticResource allCustomersListBox}">
</ListBox>
</DockPanel>
GetAll()は、ViewModelのObservableCollectionプロパティです:
public ObservableCollection<Customer> GetAll
{
get
{
return Customer.GetAll();
}
}
次に、 GetAll()モデルメソッドを呼び出します。このメソッドは、ObservableCollectionを埋めるためにXMLファイルを読み取ります。
public static ObservableCollection<Customer> GetAll()
{
ObservableCollection<Customer> customers = new ObservableCollection<Customer>();
XDocument xmlDoc = XDocument.Load(Customer.GetXmlFilePathAndFileName());
var customerObjects = from customer in xmlDoc.Descendants("customer")
select new Customer
{
Id = (int)customer.Element("id"),
FirstName = customer.Element("firstName").Value,
LastName = customer.Element("lastName").Value,
Age = (int)customer.Element("age")
};
foreach (var customerObject in customerObjects)
{
Customer customer = new Customer();
customer.Id = customerObject.Id;
customer.FirstName = customerObject.FirstName;
customer.LastName = customerObject.LastName;
customer.Age = customerObject.Age;
customers.Add(customer);
}
return customers;
}
これはすべて、ユーザーが別のビューに移動して XMLファイルを編集して、このビューに戻って 古いデータが表示されている場合を除き、すべて正常に機能します。
このビューに「バインドを更新」するよう指示するにはどうすればよいですか。実際のデータが表示されるようにします。
ここでWPFについてHTML / HTTPの比tooが多すぎるように感じます。ObservableCollectionを更新するためのより自然な方法があるので、その名前が付けられていますが、これが唯一の方法ですユーザーは、現時点でWPFアプリケーションでデータを編集できるようにします。そのため、あらゆるレベルのヘルプをここで高く評価しています。
解決
ItemsControl
はバインディングを1回要求し、その後参照をキャッシュします。
コレクションオブジェクトのコンテンツが変更され、( ObservableCollection
が行うように) INotifyCollectionChanged
を実装する場合、追加または削除されたオブジェクトを取得します。
今、バインディングが ListBox
に新しいコレクションオブジェクトを提供するようにしたい場合、ビューモデルに INotifyPropertyChanged
を実装させ、 PropertyChanged
、 GetAll
をプロパティ名として渡します。
これは、プロパティ値が変更されたことをバインディングに警告する効果があります(ピックアップする準備ができた新しい ObservableCollection
があります)。これは ListBox
に提供されます。アイテムが再生成されます。
GetAll
によって返される ObservableCollection
を操作して、アプリから変更を加える限り、追加と削除を行うことができ、リストの同期は維持されます。外部の変更(どこかに更新ボタンがある場合や、ファイル全体を再ロードするのが理にかなっている場合があります)を取得する場合は、ビューモデルで PropertyChanged
イベントを発生させることができます、プロパティゲッターを自動的に呼び出します。プロパティゲッターは静的メソッドを呼び出し、新しいメソッドを返します。
Nitpicker note:なぜプロパティにメソッド名を付けるのですか?
他のヒント
下の行は、コレクションにオブジェクトを追加するために削除したときと同じように機能します:
CollectionViewSource.GetDefaultView(CustomObservableCollection).Refresh();
ObservableCollection
への参照と、XMLファイルをロードした時点でのXMLファイルの最終変更時刻を保持します。ウィンドウがフォーカスを取得するたびに、ディスクファイルのタイムスタンプを確認します。変更されている場合は、 ObservableCollection
をクリアして再入力します。 GUIは ObservableCollection
からの変更イベントを自動的にリッスンし、コレクションのコンテンツを変更すると自動的に再入力されます。