punker76 / MahApps.Metro.SimpleChildWindow

A simple child window for MahApps.Metro
MIT License
374 stars 55 forks source link

Keep child inside parent window #44

Closed LubosBehensky closed 7 years ago

LubosBehensky commented 7 years ago

Hi,

I would like to ask if there is something wrong with what I do. I have adapted the example in the SimpleChildWindowDemo and I am trying to open movable child window like this:

           var detailWindow = new DetailWindow() { IsModal = true, AllowMove = true };

            var vm = new ProductDetailViewModel(detailWindow, payload);
            detailWindow.DataContext = vm;

            detailWindow.WindowPresenter.Content = new ProductDetailView(vm);
            await appWindow.ShowChildWindowAsync(detailWindow, appWindow.RootGrid);

DetailWindow looks like this:

<SimpleChild:ChildWindow x:Class="CategoryManager.Views.DetailWindow"
        xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:SimpleChild="clr-namespace:MahApps.Metro.SimpleChildWindow;assembly=MahApps.Metro.SimpleChildWindow"
        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:local="clr-namespace:CategoryManager.Views"
        mc:Ignorable="d"        
        ShowCloseButton="True"
        ShowTitleBar="True"
        CloseByEscape="True"                                         
        Width="auto"
        Height="auto"
        HorizontalContentAlignment="Left"
        VerticalContentAlignment="Top"        
        CloseButtonCommand="{Binding Path=CloseWindowCommand}"
        Title="Edit">

    <ContentPresenter x:Name="WindowPresenter"/>
</SimpleChild:ChildWindow>

The thing is that the opened child window can be dragged outside of bounds of parent window. In the demo application mouse movement stops at the border of the parent window.

What can I change to enforce the parent border window bounds?

epscoe commented 7 years ago

I had this problem too. For now, my workaround is to detect the mouse location in relation to the parent window's border when the child window is dropped, and if it's too far out, reset the child's RenderTransform:

protected override void OnLostMouseCapture(MouseEventArgs e)
{
    base.OnLostMouseCapture(e);

    const double offscreenMargin = 30;
    var left = dropLocation.X - offscreenMargin;
    var top = dropLocation.Y - offscreenMargin;
    var right = dropLocation.X + offscreenMargin;
    var bottom = dropLocation.Y + offscreenMargin;

    if (left < 0 || top < 0 || right > RenderSize.Width || bottom > RenderSize.Height)
    {
        var childWindow = GetTemplateChild("PART_Window") as UIElement;
        var translateTransform = childWindow?.RenderTransform as TranslateTransform;
        if (translateTransform != null)
        {
            translateTransform.X = 0;
            translateTransform.Y = 0;
        }
    }
}

This code isn't very precise, but it's enough to avoid the unrecoverable lost child scenario. Note that you can't just set the RenderTransform or its matrix to the Identity matrix, because the actual implementation is updating the X and Y values on a private TranslateTransform field (which aliases the RenderTransform property).

LubosBehensky commented 7 years ago

It is good enough for me. Thank you very much.

punker76 commented 7 years ago

@LubosBehensky It's now fixed and will be available in 1.4.0