Does WPF provide a way to render the elements of a collection on a single Viewport3D using binding?

717 views Asked by At

Note: I've omitted camera and light definitions in the XAML snippets to focus majorly on the real problem.

The problem with WPF

I would like to bind an ObservableCollection to one of WPF's 3D classes (like ModelVisual3D) In a way similar to the following:

<Viewport3D>
    <Viewport3D.Children>
        <Some3DClass ItemsSource="{Binding Objects}">
            <Some3DClass.ItemTemplate>
                <!-- definition of the template -->
            </Some3DClass.ItemTemplate>
    </Viewport3D.Children>
</Viewport3D>

However, after some research and testing, I did not found anything similar in WPF.

A solution (sort of) with Helix Toolkit

Helix toolkit is a library that offers a set of 3D components for WPF. Also, I've discovered that one of the examples (DataTemplate) claimed to provide exactly what I needed.

How does it work?

Here is a similar implementation of the xaml part of the example:

<helix:HelixViewport3D>
    <local:ItemsVisual3D ItemsSource="{Binding Objects}">
        <local:ItemsVisual3D.ItemTemplate>
            <DataTemplate3D>
                <CubeVisual3D Center="{Binding Position}" SideLength="3" Fill="OrangeRed"/>
            </DataTemplate3D>
        </local:ItemsVisual3D.ItemTemplate>
    </local:ItemsVisual3D>
</helix:HelixViewport3D>

This example works thanks to two classes:

  • ItemsVisual3D: A class that extends ModelVisual3D to contain an IEnumerable ItemsSource dependency property. It also contains a DataTemplate3D to control the rendering of the single elements of the collection.
  • DataTemplate3D: A custom template, deriving from DispatcherObject that defines that uses a Visual3D as the content property.

The issue

However, I've found a major problem: the Centers of the cubes were set correctly, but the other two properties, SideLength and Fill were not set at all, ending up with small blue cubes (by default) instead of bigger orange red cubes.

I've investigated a bit, and I realized that in DataTemplate3D.cs, only the bounded properties are set. I resolved the problem quickly, because there was a commented block of code in the function, that sets the properties defined in the template.

Then, while running the application, I've encountered one of the most obscure unexpected behaviors: All the properties were set, except for the bounded Center (i.e. I got a bunch of big orange red cubes all centered at the origin). More strangely, when I've set a breakpoint just before the function returned to check the properties, they were all set correctly, including Center, even if the output is wrong!

Conclusion

Did I miss that WPF really provides a way to bind a collection to a particular 3D class? Or did anyone found a solution on the helix toolkit side?

0

There are 0 answers