为自定义控件构建逻辑树

时间:2014-10-01 00:55:17

标签: c# wpf xaml wpf-controls logical-tree

我正在开发一个ObservableCollection作为DependencyProperties之一的控件。此属性设置为我的控件的DefaultProperty,因此我可以通过构造类似于以下内容的行隐式地将项添加到XAML中的集合:

<MyControl>
    <MyItem/>
    <MyItem/>
    <MyItem/>
</MyControl>

据我所知,WPF引擎在通过XAML解析时构建逻辑树。因此,每个MyItem应该是MyControl的逻辑子项。相反,MyControl应该是每个MyItem的逻辑父级。

嗯,显然还有更多。下面是我用来定义上述关系的代码。自定义控件包含DependencyProperty的{​​{1}},并且由CLR属性支持。

ObservableCollection

[ContentProperty("Items")] public class MyControl : Control { public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register( "Items", typeof(ObservableCollection<MyItem>), typeof(MyControl), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender, OnItemsChangedProperty)); [Category("MyControl")] public ObservableCollection<MyItem> Items { get { return (ObservableCollection<MyItem>)GetValue(ItemsProperty); } set { SetValue(ItemsProperty, value); } } public MyControl() : base() { //Set a new collection per control, but don't destroy binding. SetCurrentValue(ItemsProperty, new ObservableCollection<MyItem>()); } } (继承MyItem)开始,我尝试访问其逻辑父代,如下所示:

FrameworkContentElement

令我惊讶的是,父控件永远不会被重新渲染。这是因为if (Parent is FrameworkElement) { //Re-Render the parent control. ((FrameworkElement)Parent).InvalidateVisual(); } 属性为null。这是为什么?

如何指示WPF引擎知道MyItem.Parent应该是MyControl的逻辑父代?

1 个答案:

答案 0 :(得分:1)

如果这是针对具有多个图表的图表控件,那么您肯定在ItemsControl土地上。您可能希望查看可以从WPFToolkit或此处列出的其他工具之一构建的内容:

https://stackoverflow.com/a/4227432/1869660

至于您的实际问题,如果您确实需要手动将MyItem添加到逻辑树中,则需要拨打AddLogicalChild(),例如OnItemsChangedProperty {1}}事件。有example on MSDN