【问题标题】:How to limit child window's movement within parent boundaries?如何限制子窗口在父边界内的移动?
【发布时间】:2014-08-05 08:56:33
【问题描述】:

我想知道是否可以将子窗口的移动能力限制为仅在父面板边界内移动?假设我通过单击按钮创建了一个子窗口:

<UserControl x:Class="ChildWindowTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:Child="clr-namespace:ChildWindowTest"
mc:Ignorable="d"             
d:DesignHeight="300" d:DesignWidth="400" >

<Grid x:Name="LayoutRoot" >
    <StackPanel Width="500" Height="500">
        <Button Width="100" Height="25" Click="Button_Click" Content="Child Window"/>
    </StackPanel>
</Grid>
</UserControl>

<controls:ChildWindow 
x:Class="ChildWindowTest.ChildWindow1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
Width="400"     Height="300"    Title="ChildWindow1" >

<Grid x:Name="LayoutRoot" Margin="2">
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

</Grid>
</controls:ChildWindow>

我可以将生成的孩子在屏幕外向左、向右和向下移动(被剪掉)。我想避免这种情况,基本上设置一个允许移动子窗口的边界(在StackPanel边界内)

感谢您的任何建议..

【问题讨论】:

  • 我没有在 ChildWindow 上尝试过,但 MouseDragElementBehaviorConstrainToParentBounds="True" 可能是一个快速简单的选择。

标签: c# silverlight mdichild childwindow mdiparent


【解决方案1】:

我试图让我的解决方案尽可能简单,但要实现所需的行为仍然非常具有挑战性。

基本上,如果您不理会 ChildWindow 的 ControlTemplate,以下代码应该适合您:

private void Button_Click(object sender, RoutedEventArgs e)
{
    ChildWindow wnd = new ChildWindow();
    wnd.Width = 800;
    wnd.Height = 600;
    wnd.Title = "Test";

    wnd.MouseLeftButtonUp += wnd_MouseLeftButtonUp;
    wnd.Loaded += wnd_Loaded;

    wnd.Show();
}

private void wnd_Loaded(object sender, RoutedEventArgs e)
{
    var wnd = sender as ChildWindow;
    myApplicationActualWidth = Application.Current.Host.Content.ActualWidth;
    myApplicationActualHeight = Application.Current.Host.Content.ActualHeight;

    //This call might be necessary to make sure the visual tree of wnd is constructed and can be inspected
    wnd.UpdateLayout();

    //wnd is guaranteed to have at least one child here
    myRoot = (FrameworkElement)VisualTreeHelper.GetChild(wnd, 0);
    myContentRoot = myRoot.FindName("ContentRoot") as FrameworkElement;

    //this is the title bar part
    myChrome = myRoot.FindName("Chrome") as FrameworkElement;
    myChrome.AddHandler(MouseLeftButtonUpEvent, new MouseButtonEventHandler(wnd_MouseLeftButtonUp), true);

    myTransform = (myContentRoot.RenderTransform as TransformGroup).Children.OfType<TranslateTransform>().First();
}

private void wnd_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    Point rootMousePosition = e.GetPosition(sender as ChildWindow);
    Point contentRootMousePosition = e.GetPosition(myContentRoot);
    Point currentOffset = new Point(rootMousePosition.X - contentRootMousePosition.X, rootMousePosition.Y - contentRootMousePosition.Y);
    TransformChildWindowToValidPosition(currentOffset);
}

private void TransformChildWindowToValidPosition(Point currentPosition)
{
    // handle left side
    if (currentPosition.X < 0)
    {
        myTransform.X = myTransform.X - currentPosition.X;
    }

    // handle top
    if (currentPosition.Y < 0)
    {
        myTransform.Y = myTransform.Y - currentPosition.Y;
    }

    // handle right side
    if (currentPosition.X + myContentRoot.ActualWidth > ActualWidth)
    {
        myTransform.X = myTransform.X - (currentPosition.X + myContentRoot.ActualWidth - myApplicationActualWidth);
    }

    // handle bottom
    if (currentPosition.Y + myContentRoot.ActualHeight > ActualHeight)
    {
        myTransform.Y = myTransform.Y - (currentPosition.Y + myContentRoot.ActualHeight - myApplicationActualHeight);
    }
}

private TranslateTransform myTransform;
private FrameworkElement myRoot;
private FrameworkElement myContentRoot;
private FrameworkElement myChrome;
private double myApplicationActualWidth;
private double myApplicationActualHeight;

此代码基本上不允许您将 ChildWindow 移动到当前 SL 应用程序的边界之外,但是您可以轻松掌握窗口的“父”控件的尺寸并重新调整所有边的值。

希望我能帮上忙……

【讨论】:

  • 嗨,很抱歉延迟回复。使用上面的代码将窗口拖出时,我能够将窗口返回到屏幕内。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-19
  • 1970-01-01
  • 2010-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多