我对WPF有疑问。
我有一个Canvas作为可视化编辑器!我有几个节点'使用' X'定位在画布中和' Y'属性(Canvas.Left和Canvas.Top)。现在,我需要这个Canvas让用户放大(进出)和Pan,就像他想要的那样。
我实施了一种黑客来模仿这种行为。这是允许用户“使用”的代码。在画布周围:
///In file MainWindow.xaml.cs
private void ZoomPanCanvas_MouseMove(object sender, MouseEventArgs e) {
if (IsMouseDown) {
///Change the Cursor to Scroll
if (mNetworkUI.Cursor != Cursors.ScrollAll)
mNetworkUI.Cursor = Cursors.ScrollAll;
var currPosition = e.GetPosition(mNetworkUI);
var diff = currPosition - MouseLastPosition;
var p = new Point(diff.X, diff.Y);
mNetworkUI.ViewModel.Network.SetTransformOffset(p);
MouseLastPosition = currPosition;
}
}
///In file NetworkViewModel.cs
public void SetTransformOffset(Point newOffset) {
for (int i = 0; i < Nodes.Count; i++) {
Nodes[i].X += newOffset.X;
Nodes[i].Y += newOffset.Y;
}
}
&#39;节点&#39;是我在Canvas中显示的编辑器节点。缩放(关于鼠标位置的工作原理如下:
///File MainWindow.xaml.cs
private void ZoomPanCanvas_MouseWheel(object sender, MouseWheelEventArgs e) {
///Determine the Scaling Factor and Scale the Rule-Editor
var factor = (e.Delta > 0) ? (1.1) : (1 / 1.1);
currrentScale = factor * currrentScale;
ScaleNetwork();
///Translate the Nodes to the desired Positions
var pos = e.GetPosition(mNetworkUI);
var transform = new ScaleTransform(factor, factor, pos.X, pos.Y);
var offSet = new Point(transform.Value.OffsetX, transform.Value.OffsetY);
mNetworkUI.ViewModel.Network.SetTransformOffset(offSet);
}
///Also in MainWindow.xaml.cs
private void ScaleNetwork() {
mNetworkUI.RenderTransform = new ScaleTransform(currrentScale, currrentScale);
mNetworkUI.Width = ZoomPanCanvas.ActualWidth / currrentScale;
mNetworkUI.Height = ZoomPanCanvas.ActualHeight / currrentScale;
}
所以,在平移&#39;我计算到最后一个鼠标位置的差异,并使用该向量来操纵节点,而不是Canvas本身。 当我缩放时,我确定新的缩放,设置新的RenderTransform,调整画布大小以再次填充提供的空间,然后再次重新定位画布中的节点。
现在效果很好。我可以&amp; amp; amp;变焦&#39;围绕着我的想法,但我意识到,在我的网络中存在许多节点&#39; (连接的节点),事情变得非常缓慢。
一个原因是,在节点的每次移动中都会引发一些事件,从而导致平移时出现明显的延迟。
如何以高效的方式实现这样的事情(没有固定的Canvas-size和Scrollbars)?我有可以使用的控件吗?使用Extended WPF工具包的ZoomBox控件可以实现这一点吗?
谢谢!
答案 0 :(得分:0)
我已经为此功能编写了一个Viewport控件。
我也将其打包在nuget
上PM > Install-Package Han.Wpf.ViewportControl
它扩展了ContentControl
,其中可以包含任何FrameworkElement
,并提供受约束的缩放和平移功能。只需确保将Generic.xaml
添加到您的app.xaml
<Application.Resources>
<ResourceDictionary Source="pack://application:,,,/Han.Wpf.ViewportControl;component/Themes/Generic.xaml" />
</Application.Resources>
用法:
<Grid width="1200" height="1200">
<Button />
</Grid>