Databinding in 3D

In discussing the change to ModelVisual3D, I mentioned two benefits of the change are databinding and subclassing.  Daniel Lehenbauer has a post with a code sample that shows sub-classing 3D objects to create primitives that can be used in markup and can encapsulate lots of 3D behavior and logic.  The other thing that ModelVisual3D brings is databinding.  Here is a super simple sample that shows this in action:

Nothing fancy here.  I just embedded an XMLDataProvider inline in the XAML

  <Grid.Resources>
<XmlDataProvider x:Key="ImageData">
<data xmlns="" >
<image>https://winfx.members.winisp.net/files/chairaa.png</image>
<text>TEXT.</text>
</data>
</XmlDataProvider>
  </Grid.Resources>

And later, I do a binding to the material of the mesh, in one case an ImageBrush:

                <GeometryModel3D.Material>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<ImageBrush ImageSource="{Binding Source={StaticResource ImageData}, XPath=data/image}" />
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>

And in the other case, a VisualBrush:

                <GeometryModel3D.Material>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<VisualBrush >
<VisualBrush.Visual>
<TextBlock Text="{Binding Source={StaticResource ImageData}, XPath=data/text}" >
</TextBlock>
</VisualBrush.Visual>
</VisualBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>

Of course, there are much more sophisticated things that can be done combining the power of the Avalon's databinding with 3D.  Above and beyond just binding to materials, you can imagine doing dynamic transforms based on databindings as well as binding the camera and lights to datasources.  Lots of possibilities.

Here's the entirety of the XAML:

 

<Grid
xmlns="https://schemas.microsoft.com/winfx/avalon/2005"
xmlns:x="https://schemas.microsoft.com/winfx/xaml/2005"
>
<Grid.Resources>
<XmlDataProvider x:Key="ImageData">
<data xmlns="" >
<image>https://winfx.members.winisp.net/files/chairaa.png</image>
<text>TEXT.</text>
</data>
</XmlDataProvider>
<MeshGeometry3D x:Key="xmlData"
Positions="-1 -1 0 1 -1 0 -1 1 0 1 1 0"
Normals="0 0 1 0 0 1 0 0 1 0 0 1"
TextureCoordinates="0 1 1 1 0 0 1 0 "
TriangleIndices="0 1 2 1 3 2" />
</Grid.Resources>
<DockPanel>
<Viewport3D Name="myViewport" >
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup >
<Model3DGroup.Children>
<DirectionalLight Color="#FFFFFFFF" Direction="-3,-4,-5" />
<GeometryModel3D Geometry="{StaticResource xmlData}">
<GeometryModel3D.Material>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<VisualBrush >
<VisualBrush.Visual>
<TextBlock Text="{Binding Source={StaticResource ImageData}, XPath=data/text}" >
</TextBlock>
</VisualBrush.Visual>
</VisualBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
<GeometryModel3D.Transform>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<Rotation3D Axis="0,3,0" Angle="1" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</GeometryModel3D.Transform>
</GeometryModel3D>
</Model3DGroup.Children>
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup >
<Model3DGroup.Children>
<DirectionalLight Color="#FFFFFFFF" Direction="-3,-4,-5" />
<GeometryModel3D Geometry="{StaticResource xmlData}">
<GeometryModel3D.Material>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<ImageBrush ImageSource="{Binding Source={StaticResource ImageData}, XPath=data/image}" />
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
<GeometryModel3D.Transform>
<Transform3DGroup>
<TranslateTransform3D Offset="1 0 1">
</TranslateTransform3D>
<RotateTransform3D >
<RotateTransform3D.Rotation >
<Rotation3D Axis="0,3,0" Angle="1"/>
</RotateTransform3D.Rotation>
</RotateTransform3D>
</Transform3DGroup>
</GeometryModel3D.Transform>
</GeometryModel3D>
</Model3DGroup.Children>
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
<Viewport3D.Camera>
<PerspectiveCamera FarPlaneDistance="20" LookAtPoint="0,0,0" Up="0,1,0" NearPlaneDistance="1" Position="-5,2,3" FieldOfView="45" />
</Viewport3D.Camera>
</Viewport3D>
</DockPanel>
</Grid>