ZoomExtents方法调用的工作方式不同于通过手势激活ZoomExtets
本文关键字:激活 ZoomExtets 不同于 调用 方法 工作 方式 ZoomExtents | 更新日期: 2023-09-27 18:21:40
我一直在MVVM风格的应用程序中开发一个小的3D预览窗口。。。创建视图,然后设置其数据上下文。因此,ZoomExtentsWhenLoaded="True"似乎对我的需求没有帮助。我需要类似ZoomExtentsWhenDataContextChanges的东西。
有趣的是,我发现如果我使用下面定义的鼠标手势,我可以物理地单击HelixViewport3D,它将执行ZoomExtents。
HelixViewport3D.ZoomExtentsGesture = new MouseGesture(MouseAction.LeftDoubleClick);
但是,如果做这样的事情。。。
HelixViewport3D.DataContextChanged += (o, e) => ResetCamera();
private void ResetCamera()
{
var dc = HelixViewport3D.DataContext as WellSurveyPlot3DViewModel;
HelixViewport3D.ResetCamera();
HelixViewport3D.Camera = dc.PerspectiveCamera;
HelixViewport3D.ZoomExtents();
}
视口会缩放,只是不会像使用鼠标手势激活ZoomExtents时那样将自己居中。
我试过重置相机,还有其他一些东西。。。处理保留视口并交换DataContext而不是每次创建一个新视口的标准方法是什么?
我用附加的属性修复了这个问题。我仔细阅读了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;
}
现在,这样可以使绘制到视口中的每个新项目都具有正确的摄影机设置并缩放到一定范围。。。