如何在WPF窗口中移动一个网格面板?

3

你好,

我该如何在WPF窗口内移动(拖动)一个网格面板?网格面板没有位置或坐标属性。我只想使用鼠标将网格面板从当前位置移动到新位置,以便显示埋在其下面的控件。

有什么建议吗?

非常感谢。

4个回答

16

以下是一些代码示例,可帮助您入门:

在XAML中:

创建一个网格并定义其呈现变换:

<Grid x:Name="grid" Background="Blue" 
      Width="100" Height="100" 
      MouseDown="Grid_MouseDown" MouseMove="Grid_MouseMove" MouseUp="Grid_MouseUp">
    <Grid.RenderTransform>
        <TranslateTransform x:Name="tt"/>
    </Grid.RenderTransform>
</Grid>

指定你想要网格移动的控件名称:

<Window x:Name="window" ...>
    <Grid x:Name="grid"...
</Window>
在后端代码中:
Point m_start;
Vector m_startOffset;

private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
{
    m_start = e.GetPosition(window);
    m_startOffset = new Vector(tt.X, tt.Y);
    grid.CaptureMouse();
}

private void Grid_MouseMove(object sender, MouseEventArgs e)
{
    if (grid.IsMouseCaptured)
    {
        Vector offset = Point.Subtract(e.GetPosition(window), m_start);

        tt.X = m_startOffset.X + offset.X;
        tt.Y = m_startOffset.Y + offset.Y;
    }
}

private void Grid_MouseUp(object sender, MouseButtonEventArgs e)
{
    grid.ReleaseMouseCapture();
}

不错,但这种方法并不是很高效。当拖动包含约10个自定义模板控件的网格时,我的CPU负载会上升到23%!(Core i7 3770)难道没有更好的方法吗?我还将父容器更改为画布并使用了Canvas.SetLeft,但性能没有改变。 - SepehrM
1
渲染变换非常昂贵,特别是当您动态重新渲染一个非常复杂的控件时。没有简单的方法可以解决这个问题。一些建议:创建控件的简化副本(甚至保存图像的快照),并将此副本用于拖放渲染变换。或者:不要每次鼠标移动时都更新渲染变换。每N次命中时更新它,或仅在偏移大于某个阈值时更新它,或仅在定时间隔之后更新它等。 - Josh G
1
是的,我想我只会检查用户的图形渲染层,并在系统不是第二层时移动控件的快照。 - SepehrM
我曾经使用这种方法实现过一次3D翻转视图,效果非常流畅。目前没有可用的代码,但那正是它所做的。将控件保存为图像,然后隐藏控件并显示图像。在图像上执行所有变换,直到动画/操作完成,然后隐藏图像并再次显示实际控件,以便您可以与嵌套输入进行交互。 - Josh G

3

基于Josh G的回答

如果你想移动一个网格,Josh的回答非常好,但是它缺乏对多个元素移动的能力。
以下是如何单独移动多个元素

XAML

<Grid x:Name="gridHost">
    <Grid x:Name="gridBlue" Background="Blue" Width="100" Height="100" MouseDown="Grid_MouseDown" MouseMove="Grid_MouseMove" MouseUp="Grid_MouseUp" Margin="-100,0,0,0">
        <Grid.RenderTransform>
            <TranslateTransform/>
        </Grid.RenderTransform>
    </Grid>
    <Grid x:Name="gridRed" Background="Red" Width="100" Height="100" MouseDown="Grid_MouseDown" MouseMove="Grid_MouseMove" MouseUp="Grid_MouseUp" Margin="100,0,0,0">
        <Grid.RenderTransform>
            <TranslateTransform/>
        </Grid.RenderTransform>
    </Grid>
</Grid>

代码后台
Point m_start;
    Vector m_startOffset;

    private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
    {
        FrameworkElement element = sender as Grid;
        TranslateTransform translate = element.RenderTransform as TranslateTransform;

        m_start = e.GetPosition(gridHost);
        m_startOffset = new Vector(translate.X, translate.Y);
        element.CaptureMouse();
    }

    private void Grid_MouseMove(object sender, MouseEventArgs e)
    {
        FrameworkElement element = sender as Grid;
        TranslateTransform translate = element.RenderTransform as TranslateTransform;

        if (element.IsMouseCaptured)
        {
            Vector offset = Point.Subtract(e.GetPosition(gridHost), m_start);

            translate.X = m_startOffset.X + offset.X;
            translate.Y = m_startOffset.Y + offset.Y;
        }
    }

    private void Grid_MouseUp(object sender, MouseButtonEventArgs e)
    {
        FrameworkElement element = sender as Grid;
        element.ReleaseMouseCapture();
    }

0
    public void dragme(object sender, MouseButtonEventArgs e)
    {
        if (_Move.IsChecked == true)
            db.Attach((DependencyObject)sender);

}

//// 鼠标拖动元素行为 db;

 private void canvass_PreviewMouseDown(object sender, MouseButtonEventArgs e) 
    {
if (_Move.IsChecked == true && filmgrid.Visibility == Visibility.Visible)// == true)  
            {
                filmgrid.PreviewMouseDown += new MouseButtonEventHandler(dragme); 
            }

}


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接