I have an Adorner that is used to give visual feedback while drag'n drop. The Adorner internally uses a ContentPresenter to display (non-visual) content. When I use a Visual as content the (visual) object correctly gets rendered, but when I use a non-visual object the Adorner and its ContentPresenter only calls ToString() and does not apply any DataTemplates that are given.

Does anybody know what I'm doing wrong that the DataTemplates are not used to render the non-visual objects on Adorner layer?

Here is a simplified sample code:

Adorner:

internal class ContentAdorner : System.Windows.Documents.Adorner
{
    private readonly ContentPresenter contentPresenter = new ContentPresenter();

    public ContentAdorner(UIElement adornedElement)
        : base(adornedElement)
    {
    }

    public object Content
    {
        get
        {
            return this.contentPresenter.Content;
        }

        set
        {
            this.contentPresenter.Content = value;
        }
    }

    protected override int VisualChildrenCount
    {
        get
        {
            return 1;
        }
    }

    protected override Visual GetVisualChild(int index)
    {
        return this.contentPresenter;
    }

    protected override Size ArrangeOverride(Size finalSize)
    {
        Rect rect = new Rect(finalSize);

        this.contentPresenter.Arrange(rect);

        return finalSize;
    }

    protected override Size MeasureOverride(Size constraint)
    {
        this.contentPresenter.Measure(constraint);

        return this.contentPresenter.DesiredSize;
    }

    protected override System.Collections.IEnumerator LogicalChildren
    {
        get
        {
            ArrayList list = new ArrayList()
            {
                this.contentPresenter,
            };

            return list.GetEnumerator();
        }
    }
}

Non-visual class that is used as Content within Adorner:

    internal class Model {}

MainWindow.xaml

<Window x:Class="Adorner.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Adorner"
    Title="MainWindow" Height="350" Width="525" AllowDrop="True">
<Window.Resources>
    <DataTemplate DataType="{x:Type local:Model}">
        <Rectangle Fill="Yellow" Width="50" Height="50"/>
    </DataTemplate>
</Window.Resources>
<Grid Name="myGrid">
    <ContentControl MouseMove="ContentControl_MouseMove"
                    DragOver="ContentControl_DragOver">
        <ContentControl.Content>
            <local:Model/> 
        </ContentControl.Content>
    </ContentControl>
</Grid>

Code behind MainWindow.xaml:

    private void ContentControl_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.LeftButton == MouseButtonState.Pressed)
        {
            Model model = ((ContentControl)sender).Content as Model;

            DataObject dataObject = new DataObject("Model", model);

            DragDrop.DoDragDrop(sender as DependencyObject, dataObject, DragDropEffects.Move);
        }
    }

    private void ContentControl_DragOver(object sender, DragEventArgs e)
    {
        Model model = (Model)e.Data.GetData("Model");

        ContentAdorner adorner = new ContentAdorner(this.myGrid)
        {
            Content = model,
        };

        AdornerLayer layer = AdornerLayer.GetAdornerLayer(this.myGrid);

        layer.Add(adorner);
    }

It seems that this question handles the same problem: Click here

有帮助吗?

解决方案

I found a solution:

The Adorner layer does not know the resources of the MainWindow. You can either manually add the specific DataTemplates to the Resources of the Adorner or use the Themes/Generic.xaml together with the ThemeInfo attribute in AssemblyInfo.cs file to specify the DataTemplates.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top