0

I have a WPF application where one of the main features is a 'layout' window. In the layout window, the user can place/position/resize LayoutElements.

The place/position/resize behavior of the icons is shared; they all act the same in terms of mouse-dragging and resizing. I've implemented this behavior and it's working as I intend.

An issue with my current approach is that I've both defined DataTemplates in my main Canvas window to tell the XAML how to render the various LayoutElement subclasses, and each LayoutElement subclass has its own XAML file to define how its appearance.

For example, in my main drawing/canvas XAML, I have:

    <DataTemplate x:Key="trackTemplate">
        <local:SizingOverlay MouseDown="IconMouseDown" MouseUp="IconMouseUp" MouseMove="IconMouseMove" MouseEnter="IconMouseEnter" MouseLeave="IconMouseExit">
            <local:Track Width="128" Height="128" Canvas.Left="0" Canvas.Top="0" />
        </local:SizingOverlay>
    </DataTemplate>

The above is used by a template-lookup to say: when you have a Track LayoutElement, render it this way.

Additionally, I have Track.xaml which defines the look of the local:Track elements.

If I continue to add more LayoutElement types, I will have to keep adding more DataTemplates which basically say: for each element type, use the appropriate XAML file as the content for the SizingOverlay.

However, it seems like there should be a way to tell this DataTemplate that it contains LayoutElements, and it should use the contained concrete subclass of LayoutElement to get the XAML.

In other words: I have the abstract class LayoutElement and concrete representations of this class. How can I tell WPF to use the concrete subclass's XAML?

Here is what I've tried:

If I add an XAML layout to LayoutElement, then Track.xaml complains because it is a LayoutElement and it's conflicting with the LayoutElement.xaml definition.

If I don't have XAML for LayoutElement, then I can't do something like this:

    <DataTemplate x:Key="trackTemplate">
        <local:SizingOverlay MouseDown="IconMouseDown" MouseUp="IconMouseUp" MouseMove="IconMouseMove" MouseEnter="IconMouseEnter" MouseLeave="IconMouseExit">
            <local:LayoutElement Width="128" Height="128" Canvas.Left="0" Canvas.Top="0" />
        </local:SizingOverlay>
    </DataTemplate>

Edit: Possible duplicate

I acknowledge this question is potentially a duplicate of the following:

How to create a common WPF base window style?

Abstract class on XAML-Window

Creating an abstract base class for windows in WPF

c# WPF XAML - Working with abstract UserControls

MyUserControl cannot be the root of a XAML file because it was defined using XAML

Inheriting from a UserControl in WPF

Using an Abstract Class as DataType in DataTemplates

However, I am not sure if the questions above contain complete/appropriate answers for my use-case. They contain quite a bit of hypothetical discussion with the answers saying "I think" this, "maybe" that.

I believe I've tried the solutions proposed in the other links (particularly the last one) and it compiled, but the concrete classes were not displayed as if it couldn't find the concrete class XAML and just gave up.

I will examine those answers, and if it's clear that they apply to this question, I will delete this question. Otherwise I will update this question with a new answer (or someone else can).

afarley
  • 781
  • 6
  • 26

1 Answers1

0

I was able to get it working by replacing my abstract-class XAML element with a ContentPresenter whose content is bound to the child class.

    <DataTemplate x:Key="elementTemplate" >
        <local:SizingOverlay MouseDown="IconMouseDown" MouseUp="IconMouseUp" MouseMove="IconMouseMove" MouseEnter="IconMouseEnter" MouseLeave="IconMouseExit">
            <ContentPresenter Content="{Binding}"/>
        </local:SizingOverlay>
    </DataTemplate>
afarley
  • 781
  • 6
  • 26