user2749679
user2749679

Reputation: 51

Set Window position manually wpf mvvm

I am using WPF with MVVM pattern.

I want to set the newly opened say New Window position (Left, Top, Width, Height) dynamically by getting the co-ordinates of the other controls say Border which is on base window say Main Window. I am using the following code in Main Window:

<Window x:Class="WpfApplication3.MainWindow"
        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"
        mc:Ignorable="d"
        xmlns:local="clr-namespace:WpfApplication3"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:MainVM/>
    </Window.DataContext>
    <DockPanel>
        <StackPanel DockPanel.Dock="Left" HorizontalAlignment="Left">
            <Button Content="OK" Width="100"></Button>
        </StackPanel>
        <Border DockPanel.Dock="Top" BorderBrush="Green" Background="Black" BorderThickness="2" >
        </Border>
    </DockPanel>
</Window>

Now i want to launch the new window say New Window by clicking on OK button. Launching the new window is not a problem but i want to launch this window to the same position like Border on Main Window. New window should exactly fit in the Border on Main Window.

Upvotes: 0

Views: 1910

Answers (1)

AnjumSKhan
AnjumSKhan

Reputation: 9827

The code below solves your problem :

XAML :

<Grid>
    <Border x:Name="Brd" Margin="50,46,0,0" BorderBrush="#FFB82E2E" Background="#FFC7DC42" BorderThickness="5" CornerRadius="5">
        <Label Content="a label"/>
    </Border>
    <Button Content="Button" HorizontalAlignment="Left" Margin="32,15,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_1"/>
</Grid>

Code :

private void Button_Click(object sender, RoutedEventArgs e)
    {
        Window w = new Window();
        w.Width = Brd.ActualWidth;
        w.Height = Brd.ActualHeight;

        Point pt = Brd.PointToScreen(new Point(0, 0));
        PresentationSource source = PresentationSource.FromVisual(this);
        System.Windows.Point targetPoints = source.CompositionTarget.TransformFromDevice.Transform(pt);

        w.Top = targetPoints.Y;
        w.Left = targetPoints.X;
        w.Show();
    }

EDIT #1 (after user's request)

For pure MVVM, you have to write an attached-behavior. I have kept everything under MainWindow namespace.

Usage :

<Window.Resources>
    <Window x:Key="NewWindowKey"/>
</Window.Resources>
<Grid>
    <Border x:Name="Brd" Margin="50,46,0,0" BorderBrush="#FFB82E2E" Background="#FFC7DC42" BorderThickness="5" CornerRadius="5">            
        <Label Content="a label"/>
    </Border>
    <Button Content="Button" HorizontalAlignment="Left" Margin="32,15,0,0" VerticalAlignment="Top" Width="75">
        <local:ApplicationBehaviors.WindowPlacementBehavior>
            <local:NewWindowToShowParameters NewWindow="{StaticResource NewWindowKey}" TargetVisualName="Brd"/>
        </local:ApplicationBehaviors.WindowPlacementBehavior>
    </Button>
</Grid>

Code :

public static class ApplicationBehaviors
{
    public static NewWindowToShowParameters GetWindowPlacementBehavior(DependencyObject obj)
    {
        return (NewWindowToShowParameters)obj.GetValue(WindowPlacementBehaviorProperty);
    }

    public static void SetWindowPlacementBehavior(DependencyObject obj, NewWindowToShowParameters value)
    {
        obj.SetValue(WindowPlacementBehaviorProperty, value);
    }

    // Using a DependencyProperty as the backing store for WindowPlacement.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty WindowPlacementBehaviorProperty =
        DependencyProperty.RegisterAttached("WindowPlacementBehavior", typeof(NewWindowToShowParameters), typeof(ApplicationBehaviors), new PropertyMetadata(null, new PropertyChangedCallback(WindowPlacementChanged)));

    private static void WindowPlacementChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Button ctrl = d as Button;
        ctrl.Click += ((s, args) =>
        {
            DependencyObject parent = VisualTreeHelper.GetParent(ctrl);
            while ((parent as Window) == null)
                parent = VisualTreeHelper.GetParent(parent);

            Window rootWindow = (Window)parent;

            NewWindowToShowParameters newWindowParams = ((NewWindowToShowParameters)e.NewValue);
            Window newWin = newWindowParams.NewWindow;
            Border b = (Border) rootWindow.FindName(newWindowParams.TargetVisualName);

            newWin.Width = b.ActualWidth;
            newWin.Height = b.ActualHeight;

            Point pt = b.PointToScreen(new Point(0, 0));
            PresentationSource source = PresentationSource.FromVisual(rootWindow);
            System.Windows.Point targetPoints = source.CompositionTarget.TransformFromDevice.Transform(pt);

            newWin.Top = targetPoints.Y;
            newWin.Left = targetPoints.X;
            newWin.Show();
        });
    }        
}

public class NewWindowToShowParameters
{
    public Window NewWindow { get; set; }
    public string TargetVisualName { get; set; }
}

Upvotes: 1

Related Questions