2

I've been working on a small 3D preview window in a MVVM style application... The view is created then its data context is set. Therefore it seems that ZoomExtentsWhenLoaded="True" doesn't seem to help do what I need. I need something like, ZoomExtentsWhenDataContextChanges.

Interestingly, I've found that if I use a mouse gesture like the one defined below, I can physically click on the HelixViewport3D and it will perform a ZoomExtents.

HelixViewport3D.ZoomExtentsGesture = new MouseGesture(MouseAction.LeftDoubleClick);

However, if do something like this...

HelixViewport3D.DataContextChanged += (o, e) => ResetCamera();

private void ResetCamera()
{
    var dc = HelixViewport3D.DataContext as WellSurveyPlot3DViewModel;
    HelixViewport3D.ResetCamera();
    HelixViewport3D.Camera = dc.PerspectiveCamera;
    HelixViewport3D.ZoomExtents();
}

The viewport does zoom, it just doesn't center itself, like it does when activating ZoomExtents when using the mouse gesture.

I tried ResetCamera, and several other things... What is the standard way of dealing with keeping a viewport around and swapping out the DataContext instead of creating a new one each time?

4

1 回答 1

1

我用附加属性修复了这个问题。在注意到相机的工作原理后,我通读了 HelixViewport3D 源代码并得到了这个想法。在控件初始化后,通过属性绑定对默认相机的更新似乎并没有真正做任何事情。

      public static class HelixViewport3DZoomExtent
    {
        private static readonly Type OwnerType = typeof(HelixViewport3DZoomExtent);
        public static readonly DependencyProperty ZoomExtentsOnUpdateProperty = DependencyProperty.RegisterAttached("ZoomExtentsOnUpdate", typeof(bool), OwnerType, new PropertyMetadata(false, OnDataContextChanged));

        public static bool GetZoomExtentsOnUpdate(DependencyObject obj)
        {
            return (bool)obj.GetValue(ZoomExtentsOnUpdateProperty);
        }
        public static void SetZoomExtentsOnUpdate(DependencyObject obj, bool value)
        {
            obj.SetValue(ZoomExtentsOnUpdateProperty, value);
        }
        private static void OnDataContextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var viewport = d as HelixViewport3D;
            if (viewport == null) return;
            if (viewport.DataContext == null) return;
            viewport.Camera = viewport.DefaultCamera;
            viewport.ZoomExtents();
        }
    }

这是 Xaml

     <Border BorderBrush="Black" BorderThickness="1">

        <Grid>

            <h:HelixViewport3D Name="HelixViewport3D" 
                               PanGesture="LeftClick"
                               DataContext="{Binding PreviewPlot, UpdateSourceTrigger=PropertyChanged}"
                               DefaultCamera="{Binding PerspectiveCamera, UpdateSourceTrigger=PropertyChanged}" 
                               services:HelixViewport3DZoomExtent.ZoomExtentsOnUpdate="{Binding RelativeSource={RelativeSource AncestorType={x:Type views:WellSurveyPlot3DPreview}}, 
                                                                                        Path=DataContext.PreviewUpdatedReZoom, UpdateSourceTrigger=PropertyChanged}">

                <h:SunLight/>

                <h:TubeVisual3D  Path="{Binding TubePath}" Diameter="75" ThetaDiv="12" IsPathClosed="False" Fill="LightGray"/>

                <h:GridLinesVisual3D Width="{Binding GridLength}" Length="{Binding GridLength}" MajorDistance="{Binding MajorGridLines}" Thickness="25"
                                 MinorDistance="{Binding MajorGridLines, UpdateSourceTrigger=PropertyChanged}" LengthDirection="1,0,0" Normal="0,0,1" 
                                 Center="{Binding BottomPlaneCenter,UpdateSourceTrigger=PropertyChanged}" Fill="Red"   />
                <h:GridLinesVisual3D Width="{Binding GridLength}" Length="{Binding GridLength, UpdateSourceTrigger=PropertyChanged}" LengthDirection="0,0,1" Normal="1,0,0"  Thickness="25"
                                 MajorDistance="{Binding MajorGridLines}" MinorDistance="{Binding MajorGridLines}"
                                 Center="{Binding BackLeftPlaneCenter, UpdateSourceTrigger=PropertyChanged}" Fill="Blue" />
                <h:GridLinesVisual3D Width="{Binding GridLength}" Length="{Binding GridLength, UpdateSourceTrigger=PropertyChanged}" LengthDirection="1,0,0" Normal="0,1,0" Thickness="25"
                                 MajorDistance="{Binding MajorGridLines}" MinorDistance="{Binding MajorGridLines}" 
                                 Center="{Binding BackRightPlaneCenter,UpdateSourceTrigger=PropertyChanged}" Fill="Green" />

            </h:HelixViewport3D>

            <Button Content="Open Well Viewer" HorizontalAlignment="Left"  VerticalAlignment="Top" Command="{Binding OpenWindowCmd}"/>

        </Grid>
    </Border>

在我的视图模型中,我必须切换我的 PreviewUpdateReZoom 属性。

    private void LoadSurveyPoints(List<WellSurveyPointCalculated> surveyPoints)
        {
            _coordinatesCalculator = _calcGlobalCoordsFactory.Create(surveyPoints);
            _wellXyzCoordinates = _coordinatesCalculator.PlotGlobalCoordinates(100).ToList();
            PreviewPlot = WellSurveyPlot3DViewModel();
            PreviewUpdatedReZoom = false;//Toggle true false to send property changed and get attached property to fire.
            PreviewUpdatedReZoom = true;
        }

现在,这可以使绘制到视口中的每个新项目都具有正确的相机设置并缩放到范围...

于 2014-09-14T18:25:16.417 回答