Reputation: 51
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
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