Объединение ItemsControl с перетаскиваемыми элементами - Element.parent всегда пусто - PullRequest
8 голосов
/ 11 октября 2010

Я связываю ItemsControl с Canvas в виде ItemsPanelTemplate с ObservableCollection.

Я хочу сделать элементы перетаскиваемыми с помощью DraggableExtender, как указано в Перетаскивание изображения в 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 Ответ

8 голосов
/ 11 октября 2010

Поскольку элементы не находятся непосредственно внутри холста, вам нужно пройти вверх по визуальному дереву, пока не найдете холст. Я обычно использую следующий метод расширения, чтобы сделать это:

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>();
...