2010-12-27 11 views
9

ItemsSourceプロパティを持つUserControlがあります。基本ユーザーコントロールクラスがのItemsSourceを実装していませんので、私はこのような私自身の依存関係プロパティを作成する必要がありました:カスタムItemsSource依存関係プロパティを持つユーザーコントロール

#region ItemsSource Dependency Property 
    public static readonly DependencyProperty ItemsSourceProperty = 
     DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(MonthViewControl), 
     new PropertyMetadata(OnItemsSourceChanged)); 

    static void OnItemsSourceChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
    { 
     (obj as MonthViewControl).OnItemsSourceChanged(e); 
    } 

    private void OnItemsSourceChanged(DependencyPropertyChangedEventArgs e) 
    { 
     RefreshLayout(); 
    } 

    public IEnumerable ItemsSource 
    { 
     get 
     { 
      return (base.GetValue(ItemsSourceProperty) as IEnumerable); 
     } 
     set 
     { 
      base.SetValue(ItemsSourceProperty, value); 
     } 
    } 

    #endregion 

は今私のViewModelに私はそうのようなEventItemアイテムのICollectionViewにあるイベント性質を持っています

private ObservableCollection<Controls.EventCalendar.EventItem> eventItems; 
    private CollectionViewSource events; 
    public System.ComponentModel.ICollectionView Events 
    { 
     get 
     { 
      if (events == null) 
      { 
       events = new CollectionViewSource(); 
       events.Source = eventItems; 
      } 

      return events.View; 
     } 
    } 

私が直面している問題は、EventsプロパティにバインドするとEventItemsにItemを追加すると、UserControlはItemsSourceChangedイベントを発生させず、したがってUIを更新しないということです。 テストのために、私はEventsプロパティにもバインドする単純なリストボックスをビューに追加しました。それは魅力のように機能します。 eventItems observableCollectionの更新はListBoxに反映されます。

私はItemsSource依存関係プロパティと関係があると考えています。たぶん私はUserControlの代わりにフォームItemsControlを継承するカスタムコントロールを使用する必要がありますか?

私の問題を理解するのに役立ちます:イベント/予定表エントリ(Googleカレンダーに似ています)を示すコントロールのようなカレンダーを作成しようとしています。それは魅力のように働く。コントロールのサイズを変更するとUIが更新されます。残っている唯一のことは、ItemsSourceが変更されると自動アップデートです。

誰かが助けてくれることを願っています。

EDIT:私が投稿した瞬間、ItemsSourceプロパティが変更されないため、イベントを起動できないことに気付きました。変更されるのは基礎となるコレクションです。しかし、私はそれをどう扱うかではありません。この作業をするためには何を実装する必要がありますか?ただのヒントで十分でしょう。私はすべての実装の詳細を必要としません。

答えて

6

リフレクター内PresentationFramework.dllを開くとSystem.Windows.Controls.ItemsControlを見ては、次のことを示した:

public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IEnumerable), 
    typeof(ItemsControl), new FrameworkPropertyMetadata(null, 
    new PropertyChangedCallback(ItemsControl.OnItemsSourceChanged))); 

private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{ 
    ItemsControl control = (ItemsControl) d; 
    IEnumerable oldValue = (IEnumerable) e.OldValue; 
    IEnumerable newValue = (IEnumerable) e.NewValue; 
    ItemValueStorageField.ClearValue(d); 
    if ((e.NewValue == null) && !BindingOperations.IsDataBound(d, ItemsSourceProperty)) 
    { 
     control.Items.ClearItemsSource(); 
    } 
    else 
    { 
     control.Items.SetItemsSource(newValue); 
    } 
    control.OnItemsSourceChanged(oldValue, newValue); 
} 

RefreshLayoutは私の直感は、それが道とは何かを持っていることである何をするか知りませんObservableCollection<T>は、上記のコードが具体的なコレクション型とは無関係にラップされているため、ラップされる型によって処理されます。この場合はObservableCollection<T>以下のようにプロパティを変更してデフォルトのビューを返し、フレームワークの上のコードに近いようにItemsSourceプロパティを調整し、そこから後方に作業してください。

private ObservableCollection<Controls.EventCalendar.EventItem> eventItems; 
private ICollectionview eventsView; 
public System.ComponentModel.ICollectionView Events 
{ 
    get 
    { 
     if (eventsView == null) 
      eventsView = CollectionViewSource.GetDefaultView(eventItems); 
     return eventsView; 
    } 
} 
+0

ご迷惑をおかけして申し訳ありません。私はあなたの答えを「答え」と記し、行く方法のように見せます。しかし、私はそれを試していないので、私は確かに言うことができません。確かに、私はItemsControlを継承しているUserControlからCustomControlへコントロールを再設計することにしました。 –