ItemSource in HelixViewport3D using MVVM

Apr 25, 2012 at 6:05 AM

 

Hello,

I have a problem in using the HelixViewport3D in a MVVM context. My ItemSource is an ObservableCollection of Visual3D-Elements and it works well when I change the Collection after the Viewport is created and the Binding to the Collection is done. But in my case the Collection is not empty when I create the Viewport and then the initial Elements are not drawn in the Viewport. I think the Viewport should refresh the Viewport-Elements when the ItemSource-Property changes. Would it be possible to implement this in the HelixViewport3D class?

 Andreas

Jun 26, 2012 at 7:27 AM

 

Hello,

to solve this problem I added the following code in HelexViewport3D:

 

        protected override void OnItemsSourceChanged(System.Collections.IEnumerable oldValue, System.Collections.IEnumerable newValue)
        {
            base.OnItemsSourceChanged(oldValue, newValue);
 
            if (oldValue != null)
            {
                foreach (var element in oldValue)
                {
                    var visual = element as Visual3D;
                    if (visual != null)
                    {
                        this.Children.Remove(visual);
                    }
                }
            }
 
            if (newValue != null)
            {
                foreach (var element in newValue)
                {
                    var visual = element as Visual3D;
                    if (visual != null)
                    {
                        this.Children.Add(visual);
                    }
                }
            }
        }

Would it be possible to add this to the current Version of Helix?

Thanks
Andreas

 

 

 

Coordinator
Jun 26, 2012 at 8:02 AM

Thanks for the solution! Checked in the code!

Aug 24, 2012 at 8:02 AM
Edited Aug 24, 2012 at 8:11 AM

I 'm posting here since it's related issue. Not sure if it would be helix-specific or WPF-specific though :)

I want to have for boxes with text (tags) on them and arrows that show their rotation (direction) in 3D space. I also want to hide/show the arrows and the text.

As in MVVMDemo of the toolkit I use a Collection for the Boxes, and also other collections to seperate the text and the arrows. In the XAML I use MultiBinding and a Converter which merges the collections so they can be aggregated to the ItemSource of the Viewport. I also have a seperate collection for the lights. I already use relay commands to check boxes to how or hide the text or the arrows.

I' m doing the job this way, but I 'm thinking of altering this approach because as it is I have to put so much code in the ViewModel to create each box and bind the arrow and the text position to it. I 'm thinking of creating a datatemplate somehow holding a ContainerUIElement3D as root element and holds a BoxVisual3D, a TextVisual3D and an ArrowVisual3D. This is not possible as I 've tested and read, so I probably have to place it in a ResourceDictionary. The other option is to place text and arrow as children of the BoxVisual3D.

Since I don't have much experience using MVVM, I would like to ask how can I have a "DataTemplate" of that ResourceDictionary similar to what I can perform id 2D:

<DataTemplate DataType="{x:Type local:ObjectViewModel}"><local:ObjectView /> </DataTemplate> 

and having my SceneViewModel (it's View has the Viewport) to have a Collection of ObjectViewModels, so that it can draw my ObjectViewModel. The ViewModel would have a constructor that takes the Model.

Is there any other solution that applies to my problem?

 

 

 

 

 

Nov 9, 2012 at 9:15 AM

Yes, I miss Databinding in 3d, too. There seems to be no way to bind a collection of objects to the viewport's or to a Visual3D's Children property just as you would do in 2d. Is there anything we can do using the Helix Viewport?

Coordinator
Nov 12, 2012 at 8:15 PM

I think it should be possible to implement a new "DataTemplate3D" class similar to DataTemplate. DataTemplate cannot be used since it only allows FrameworkElement content. Then it should be possible to implement an "ItemsVisual3D" class that creates Visual3D instances from the DataTemplate3D. But I think it is a challenge to set up the bindings, since Visual3D/Model3D objects does not have data contexts...

http://stackoverflow.com/questions/7725313/how-can-i-use-databinding-for-3d-elements-like-visual3d-or-uielement3d

Coordinator
Nov 12, 2012 at 9:08 PM

I added an experimental example to ExampleBrowser/Examples/DataTemplate. The template factory method needs more work to be useful...

Nov 13, 2012 at 8:16 AM
objo wrote:

I think it should be possible to implement a new "DataTemplate3D" class similar to DataTemplate...

I really like this idea! And I would really appreciate if there is a solution for this problem some day. I'm currently working on an application where content is displayed in a 3d viewport and the user can directly interact with the 3d objects. At first I thought, I simply could bind my ViewModel against the viewport's content the way I built all my WPF applications. But then I realized it wouldn't work because something like the "DataTemplate3D" is missing.

It would be great to define Templates, Styles and Triggers to change the appearance of the 3d objects and make everything work like in "normal" WPF. I looked into your sample and I definitely like the idea of the DataTemplate3D and the ItemsVisual3D!

Christian

May 14, 2013 at 12:57 PM
Edited May 14, 2013 at 12:57 PM
I update the code of datatemplate3D and now it works for properties
        var prop = type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);
        foreach (var p in prop)
        {
            if (p.CanWrite && !boundProperties.Contains(p.Name))
            {
                var value = p.GetValue(this.Content, null);
                p.SetValue(visual, value, null);
            }
        }
Coordinator
Jun 7, 2013 at 9:47 AM
yes, this should copy the values of the properties - but I would like to see a solution that uses bindings! I have not checked how it is done for DataTemplate, but I think the solution should be somewhere in PresentationFramework.dll :-)