2014-09-24 75 views
2

我有一個用於執行動態數據呈現的自定義控件。此控件包含一組DataPoint對象,並且每個DataPoint都基於其位置(控制點繪製在OnRender方法中)呈現在控件中。添加集合項目時,OnRender不會調用?

自定義控件包含許多DependencyProperties影響渲染的圖像,因此具有FrameworkPropertyMetadata描述了控制應呈現,如果屬性的變化:

public static readonly DependencyProperty DataPointsProperty = 
    DependencyProperty.Register(
     "DataPoints",          //Property Name 
     typeof(List<DataPoint>),       //CLR-Property Type 
     typeof(MyCustomControl),       //Custom Control Type 
     new FrameworkPropertyMetadata(
      new List<DataPoint>(),       //Default Value. 
      FrameworkPropertyMetadataOptions.AffectsRender //Re-render if changed 
     ) 
    ); 

遺憾的是,重新渲染確實NOT發生在新的DataPoint時,將添加到此集合中。

如何添加新的DataPoint時,如何配置我的自定義控件以便調用OnRender方法?

除了程序的運行時間以外,重新呈現必須發生在WPF設計器中。

+1

沒有這個**大膽**也人們可以很好地閱讀這個問題。我已經編輯了你的問題。 – 2014-09-24 18:45:47

回答

4

首先,List<T>不支持更改通知,而WPF的內置集合做了支持更改通知並非來自List<T>。我建議您使用IList<T>IEnumerable<T>作爲您的房產類型。第二,每當新的集合被分配到DataPoints(驗證它實現INotifyCollectionChanged後),並且使用該處理程序調用InvalidateVisual()時,您將需要添加集合更改處理程序。最簡單的方法是在註冊DataPoints依賴項屬性時指定屬性更改回調。

public static readonly DependencyProperty DataPointsProperty = 
    DependencyProperty.Register(
     "DataPoints",          //Property Name 
     typeof(IList<DataPoint>),       //CLR-Property Type 
     typeof(MyCustomControl),       //Custom Control Type 
     new FrameworkPropertyMetadata(
      default(IList<DataPoint>),      //Default Value. 
      FrameworkPropertyMetadataOptions.AffectsRender, //Re-render if changed, 
      OnDataPointsPropertyChanged 
     ) 
    ); 

private static void OnDataPointsPropertyChanged(
    DependencyObject d, 
    DependencyPropertyChangedEventArgs e) 
{ 
    var control = (MyCustomControl)d; 

    var oldValue = e.OldValue as INotifyCollectionChanged; 
    var newValue = e.NewValue as INotifyCollectionChanged; 

    if (oldValue != null) 
     oldValue.CollectionChanged -= control.OnDataPointsCollectionChanged; 

    if (newValue != null) 
     newValue.CollectionChanged += control.OnDataPointsCollectionChanged; 
} 

private void OnDataPointsCollectionChanged(
    object s, 
    NotifyCollectionChangedEventArgs e) 
{ 
    this.InvalidateVisual(); 
} 

最後,不要指定默認屬性值的集合實例:這將導致所有實例共享相同的集合(除非分配一個新的)。相反,初始化您的構造函數中的屬性:

public MyCustomControl() 
{ 
    // ... 
    SetCurrentValue(DataPointsProperty, new ObservableCollection<DataPoint>()); 
} 
+1

+1提醒我在初始化引用類型依賴項屬性時使用SetCurrentValue而不是本地值。 – Clemens 2014-09-24 19:13:34

+0

太棒了!有用。順便說一下,如果集合具有在XAML中指定的項目,則「IList」將不起作用,因爲它只允許1個子元素(並且該子元素不是列表項)。但是,將其更改爲「ObservableCollection」允許我在XAML中指定項目。 – 2014-09-24 19:53:17

+1

非泛型'IList'應該在Xaml中正常工作,但'IList '可能不會。我相信Xaml只支持'IList'和'IAddChild'。 – 2014-09-25 13:38:12

相關問題