早上好,提前谢谢你回答。
我的观点实现了一个平底锅和一个缩放库:A WPF Custom Control for Zooming and Panning
在视图中,有一个控件可以根据鼠标双击缩放到一个点:
private void zoomAndPanControl_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
if ((Keyboard.Modifiers & ModifierKeys.Shift) == 0)
{
Point doubleClickPoint = e.GetPosition(content);
zoomAndPanControl.AnimatedSnapTo(doubleClickPoint);
}
}
我想强制“zoomAndPanControl。 AnimatedSnapTo (doubleClickPoint);”基于我绘制的几何点的ViewModel数据的特定点,当我拉它时。因此,视图将平移到新几何x,y coords的点。几何/点已绑定到视图。
作为补充说明,在DispatchTimer中提取几何点的数据。随着新几何坐标的读取,我希望看到pan& amp;请遵循这些协调。
当我获取数据时,是否有一种从ViewModel访问此控件的简单方法?可能使用自定义点模拟鼠标事件?我不确定最好的方法。
答案 0 :(得分:2)
要控制您通过绑定查看,您的控件需要绑定到的内容。
希望有所帮助。
答案 1 :(得分:1)
我通常处理这类场景的方法是在ViewModel上定义一个委托,在View中设置它,并在需要时调用它:
在ViewModel中定义一个方法,该方法为当前鼠标位置接收Action<Point>
和Point
对象:
public void ExecuteAnimatedSnapTo(Action<Point> animatedSnapToAction, Point pointerPosition)
{
if (animatedSnapToAction != null && pointerPosition != null)
{
// Create a new point based on the one passed in and data in ViewModel
Point newPoint =
new Point(pointerPosition.X + viewModelData.X, pointerPosition.Y + viewModelData.Y);
// Invoke the delegate using the new point
animatedSnapToAction(newPoint);
}
}
然后在View后面的代码中,执行以下方法:
private void zoomAndPanControl_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
if ((Keyboard.Modifiers & ModifierKeys.Shift) == 0)
{
Point doubleClickPoint = e.GetPosition(content);
var viewModel = (MyViewModel)this.DataContext;
viewModel.ExecuteAnimatedSnapTo(zoomAndPanControl.AnimatedSnapTo, doubleClickPoint);
}
}
使用这种方法,您仍然可以保留视图与ViewModel的隔离。当[unit]测试VM时,委托和点在传递给方法时可能为null。然后if
块会阻止&#34; UI&#34;被测试的逻辑。
您需要注意的一件事是,如果ViewModel数据是在另一个线程上计算的,那么您必须在UI调度程序上执行委托。
我认为ViewModel具有在MouseDoubleClick
被触发时调用委托所需的所有数据。如果情况并非如此,那么更好的解决方案是将Action
作为VM上的属性公开,并在需要时调用它:
public Action<Point> AnimatedSnapToAction { get; set; }
在View上创建VM实例时,也要设置属性:
public MyView()
{
InitializeComponent();
MyViewModel viewModel = new MyViewModel();
viewModel.AnimatedSnapToAction = zoomAndPanControl.AnimatedSnapTo;
this.DataContext = viewModel;
}
现在,您可以在需要时在VM上执行委托。例如,如果需要在DispatcherTimer
的刻度线上调用它,它将如下所示:
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
// Calculate geometry data
if(AnimatedToSnapAction != null)
{
AnimatedSnapToAction(pointCalculatedUsingGeometryData);
}
}
答案 2 :(得分:0)
视图模型应该公开您的视图需要显示和交互的数据和行为,它应该永远不会引用View本身。
View隐式或显式地具有对ViewModel的引用。通过此引用,您可以调用方法,绑定数据,挂钩事件等...
为了简单起见,在这种情况下,您可能希望在用户双击控件时在ViewModel上执行命令,然后可以在命令执行中修改ViewModel公开的任何公共属性。然后可以使用这些属性来确定要缩放的点。