将ItemsControl与可拖动项组合 - Element.parent始终为null

时间:2010-10-10 22:02:33

标签: wpf canvas draggable parent itemscontrol

我将ItemsControl与Canvas绑定为ItemsPanelTemplate到ObservableCollection。

我想使用发布的DraggableExtender使项目可拖动 Dragging an image in WPF (我不想使用变换 - 我需要使用Canvas Left和Top属性)

它被定义为:

    <ItemsControl ItemsSource="{Binding Path=Nodes}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas IsItemsHost="True" />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Views:NodeView DataContext="{Binding}"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.ItemContainerStyle>
            <Style TargetType="ContentPresenter">
                <Setter Property="Utilities:DraggableExtender.CanDrag" Value="True" />
                <Setter Property="Canvas.Left" Value="{Binding Path=X}" />
                <Setter Property="Canvas.Top" Value="{Binding Path=Y}" />
            </Style>
        </ItemsControl.ItemContainerStyle>
    </ItemsControl>

DraggableExtender需要元素的父元素为Canvas, 但是我的元素(contentpresenter)的父元素为空,因此拖动不起作用。

所以显而易见的问题是 - 我做错了什么?

1 个答案:

答案 0 :(得分:8)

由于项目不直接位于画布内,因此您需要沿着可视树向上走,直到找到画布。我通常使用以下扩展方法来执行此操作:

public static T FindAncestor<T>(this DependencyObject obj)
    where T : DependencyObject
{
    DependencyObject tmp = VisualTreeHelper.GetParent(obj);
    while(tmp != null && !(tmp is T))
    {
        tmp = VisualTreeHelper.GetParent(tmp);
    }
    return tmp as T;
}

将上面的方法放在静态类中,并导入声明它的命名空间。在DraggableExtender代码中,只需替换此行:

Canvas canvas = element.Parent as Canvas;

有了这个:

Canvas canvas = element.FindAncestor<Canvas>();