0

I would like to instantiate a class defined in C# in XAML and use it in both XAML and code. I found out that I can instantiate the object as a resource and use TryFindResource("...") to locate it in code but I am confused about how I should reference it later in XAML. Fore example, I have the following XAML code:

<UserControl.Resources>
    <localx:PipeViewModel x:Key="pipeview" />
</UserControl.Resources>


<DockPanel  Grid.Row="0" Grid.RowSpan="3" Grid.ColumnSpan="3" Grid.Column="0" Background="White">
    <hx:HelixViewport3D x:Name="HelixViewport3D" 
                        ZoomExtentsWhenLoaded="True" 
                        CameraRotationMode="Trackball" 
                        CameraMode="FixedPosition"
                        PanGesture="LeftClick">
        <hx:DefaultLights  />
        <hx:DefaultLights  />
        <localx:PipeViewModel x:Name="pipeview" MyPipeModel="{Binding Path=PipeModel, RelativeSource={RelativeSource AncestorType=UserControl, AncestorLevel=1}}"/>
    </hx:HelixViewport3D>
</DockPanel>

I am not sure if the object instantiated in the resource section is the same one inserted in HelixVievPort3D. I suspect that using the same names doe not necessarily imply they are the same. How can I correctly insert the pipeview object in HelixViewPort?

I. Konuk
  • 59
  • 8
  • A view model object would usually not be added to an element tree. You would instead assign it to the DataContext property of a view element to use it as the source of Bindings. – Clemens Nov 24 '20 at 16:34
  • Clemens: Thank you for your feedback. I am sorry but I do not follow MVVM so strictly. As you may suspect from labels, my ViewModel object combines both the View and ViewModel. It does contain the visual element I want to insert it to the viewport. So my question is still open. – I. Konuk Nov 24 '20 at 17:00
  • Sounds terrible. However, search StackOverflow for how to use StaticResourceExtension to use a UIElement resource. – Clemens Nov 24 '20 at 17:03

1 Answers1

1

Indeed, declaring elements like this creates new instances. This is called Object element syntax. Consequently, the PipeViewModel declared in the resources section is a different instance than in the viewport.

Object element syntax is the XAML markup syntax that instantiates a CLR class or structure by declaring an XML element.

In XAML, you can reference resources using the StaticResource or DynamicResource markup extenstions. For the difference between both, you can refer to this related question.

You should be able to use one of the markup extensions as tag to use the element in your viewport:

<hx:HelixViewport3D x:Name="HelixViewport3D" 
                    ZoomExtentsWhenLoaded="True" 
                    CameraRotationMode="Trackball" 
                    CameraMode="FixedPosition"
                    PanGesture="LeftClick">
   <hx:DefaultLights/>
   <hx:DefaultLights/>
   <StaticResource ResourceKey="pipeview"/>
</hx:HelixViewport3D>

Since the instance in your resources is now the only one, you might want to add the binding there.

<UserControl.Resources>
    <localx:PipeViewModel x:Key="pipeview" MyPipeModel="{Binding Path=PipeModel, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
</UserControl.Resources>

As you commented on your question, the PipeViewModel is a mixture of view model and view. I strongly recommend you to use MVVM for a clear separation of view, data and business logic, otherwise understanding, extending and maintaining your application will be hard in the long run.

thatguy
  • 21,059
  • 6
  • 30
  • 40
  • thatguy: THANK you indeed very much for a very comprehensive response. Yes, indeed I had the binding in my code already exactly like you recommend. I will make my current design work first and then follow the other suggestions. – I. Konuk Nov 24 '20 at 18:13