2010-12-27 11 views
9

Posiadam UserControl z właściwości ItemsSource. Jako klasa bazowa UserControl nie implementuje ItemsSource, musiałem stworzyć własną właściwość zależność tak:Kontrola użytkownika z niestandardową właściwością zależność 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 

Teraz w moim ViewModel mam właściwości zdarzenia, które jest ICollectionView przedmiotów EventItem tak:

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; 
     } 
    } 

Problem, przed którym stoję, polega na tym, że w moim widoku, po powiązaniu z właściwością Zdarzenia i dodaniu elementu do elementu eventItems, UserControl nie uruchomi zdarzenia ItemsSourceChanged, a zatem nie zaktualizuje interfejsu użytkownika. Dla celów testowania dodałem prosty widok listy do widoku, który również wiąże się z właściwością Zdarzenia. To działa jak urok. Aktualizacje obiektu eventItems obserwowalneKolekcje są odzwierciedlane w polu ListBox.

Domyślam się, że ma to coś wspólnego z moją właściwością zależności ItemsSource. Może musiałbym użyć Custom Control, który dziedziczy ItemControl zamiast UserControl?

Aby pomóc w zrozumieniu mojego problemu: Próbuję utworzyć kalendarz, taki jak kontrolka, który pokazuje wpisy zdarzeń/agend (podobne do kalendarza Google). To działa jak urok. Interfejs użytkownika jest aktualizowany po zmianie rozmiaru kontrolki. Pozostaje tylko aktualizacja automatyczna po zmianie w ItemSource.

Mam nadzieję, że ktoś może pomóc.

EDYCJA: W momencie opublikowania zdałem sobie sprawę, że zdarzenia nie można uruchomić, ponieważ właściwość ItemsSource się nie zmienia. Jest to podstawowa kolekcja, która się zmienia. Jednak nie jestem w stanie sobie z tym poradzić. Co muszę zaimplementować, aby to działało. Wystarczy wskazówka. Nie potrzebuję szczegółów każdego wdrożenia.

Odpowiedz

6

Otwarcie PresentationFramework.dll wewnątrz reflektora i patrząc na System.Windows.Controls.ItemsControl wykazała co następuje:

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); 
} 

Nie wiedząc, co robi mój RefreshLayout przeczucie, że to ma coś wspólnego ze sposobem ObservableCollection<T> jest zawijany, ponieważ powyższy kod jest niepomny na to, jaki jest konkretny typ kolekcji, dlatego byłby obsługiwany przez zawijany typ; w tym przypadku: ObservableCollection<T> Spróbuj zmodyfikować swoją własność, tak jak pokazano poniżej, aby przywrócić domyślny widok i dostosować właściwość ItemsSource, aby była bardziej zbliżona do powyższego kodu z frameworka i zacznij od tego miejsca.

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

Przepraszamy za spóźnioną odpowiedź. Zamierzam oznaczyć twoją odpowiedź jako "Odpowiedź", ponieważ wygląda jak droga. Nie mogę jednak powiedzieć tego na pewno, ponieważ tego nie próbowałem. Rzeczywiście, postanowiłem przeprojektować sterowanie z UserControl na CustomControl, który dziedziczy z ItemsControl i wydaje się (na razie), aby rozwiązać problem. –

Powiązane problemy