私はcomposite design patternを使用するフォルダのような構造を持っていて、私はTreeView
にルートフォルダをバインドします。私はフォルダの内容から蓄積されている特定のプロパティを表示することができれば非常に便利です。問題は、子要素に変更が発生して累積プロパティが更新されるようにフォルダに通知するにはどうすればよいですか?変更通知をバインディングの階層構造の上位に伝播するにはどうすればよいですか?
私が必要とする文脈は、私が作ろうとしている小さなRSSフィードリーダーです。これは私のモデルの中で最も重要なオブジェクトおよび側面です:
コンポジットインターフェース:
public interface IFeedComposite : INotifyPropertyChanged
{
string Title { get; set; }
int UnreadFeedItemsCount { get; }
ObservableCollection<FeedItem> FeedItems { get; }
}
FeedComposite(別名フォルダ)
public class FeedComposite : BindableObject, IFeedComposite
{
private string title = "";
public string Title
{
get { return title; }
set
{
title = value;
NotifyPropertyChanged("Title");
}
}
private ObservableCollection<IFeedComposite> children = new ObservableCollection<IFeedComposite>();
public ObservableCollection<IFeedComposite> Children
{
get { return children; }
set
{
children.Clear();
foreach (IFeedComposite item in value)
{
children.Add(item);
}
NotifyPropertyChanged("Children");
}
}
public FeedComposite() { }
public FeedComposite(string title)
{
Title = title;
}
public ObservableCollection<FeedItem> FeedItems
{
get
{
ObservableCollection<FeedItem> feedItems = new ObservableCollection<FeedItem>();
foreach (IFeedComposite child in Children)
{
foreach (FeedItem item in child.FeedItems)
{
feedItems.Add(item);
}
}
return feedItems;
}
}
public int UnreadFeedItemsCount
{
get
{
return (from i in FeedItems
where i.IsUnread
select i).Count();
}
}
フィード:
public class Feed : BindableObject, IFeedComposite
{
private string url = "";
public string Url
{
get { return url; }
set
{
url = value;
NotifyPropertyChanged("Url");
}
}
...
private ObservableCollection<FeedItem> feedItems = new ObservableCollection<FeedItem>();
public ObservableCollection<FeedItem> FeedItems
{
get { return feedItems; }
set
{
feedItems.Clear();
foreach (FeedItem item in value)
{
AddFeedItem(item);
}
NotifyPropertyChanged("Items");
}
}
public int UnreadFeedItemsCount
{
get
{
return (from i in FeedItems
where i.IsUnread
select i).Count();
}
}
public Feed() { }
public Feed(string url)
{
Url = url;
}
私がを縛るならば、ここに事がありますからUnreadFeedItemsCount
にアイテムが未読とマークされている場合、簡単な通知はありません。私のアプローチの1つはFeedItem
のPropertyChanged
イベントを処理することでした。IsUnread
- プロパティが変更された場合、私はFeed
プロパティUnreadFeedItemsCount
が変更されました。このアプローチでは、すべてのイベントをすべてFeeds
とFeedComposites
のChildren
のFeedComposite
というイベントで処理する必要があります。そのサウンドから、これはあまり良いアイデアではないことが明らかです。最初にPropertyChanged
イベントハンドラをアタッチしなくても、任意のコレクションに追加または削除できます。
また、私はCollectionChanged
で何をしていますか?未読アイテム数の合計にも変化が生じる必要がありますか?より多くのイベント処理の楽しみのように聞こえる。
このような混乱です。何年も前に私がデータバインディングについて知りませんでしたが、フィードリーダーが私の最初の試みほどひどくなることを望んでいないので、誰かがこれに優雅な解決策を持っているなら、素晴らしいでしょう...
回答ありがとうございました。ここでかなりの長さになりました。今すぐ私はあなたに長い応答を与えることはできません、私はできるだけ早くそうしようとします... –
私はあなたの答えが好きではないいくつかのことがあります。既存のもの以外の他のオブジェクトがそれらを実装する可能性も非常に低くなります。また、FeedCompositeのChildrenをFoldersのフィードに分割してIFeedCompositeインターフェイスを使用せず、実質的に同一で、1つに置き換えることのできる多くのメソッドを持たせることで、コンポジットパターンを削除しました。より面倒で、フィードとフォルダの混在した順序を持つことはできません。 –
私のオリジナルのソリューションには、オブジェクトをコレクションに追加するときにハンドラーを追加するヘルパーメソッドと同じものがありましたが、この質問で指摘したように、他の提案が良いかもしれません。あなたの答えにはいくつかのものがありますが、これは便利なような拡張メソッドのように役立ちますので、努力していただきありがとうございます。 –