如何限制子窗口在父边界内的移动?

时间:2014-08-05 08:56:33

标签: c# silverlight mdichild childwindow mdiparent

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

<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边界内)

感谢您的任何建议..

1 个答案:

答案 0 :(得分:0)

我尽量保持我的解决方案尽可能简单,但实现理想的行为仍然非常具有挑战性。

基本上,如果您单独留下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应用程序的边界之外,但它应该是一块蛋糕,让你的手掌握窗口的“父”控件的尺寸,并重新调整所有边缘的值。

希望我能帮忙......