手动设置窗口位置wpf mvvm

手动设置窗口位置wpf mvvm

问题描述:

我正在使用带有MVVM模式的WPF。手动设置窗口位置wpf mvvm

我想通过获取其他控件的坐标动态地设置新打开的说新窗口位置(左,顶部,宽度,高度),说在基础窗口上的边界说主窗口。 我使用下面的代码在主窗口:

<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> 

现在我要启动的新窗口中点击OK按钮,说新窗口。 启动新窗口不是一个问题,但我想启动这个窗口到像主窗口边框一样的位置。 新窗口应该完全适合主窗口上的边框。

+0

@Dheeraj这不是重复。 – Kcvin

+0

窗口的定位是一个仅供查看的相关问题,因此您不应该试图在您的ViewModel中的属性中绑定顶部,左侧,宽度,高度 - 相反,请在代码背后执行 – Kcvin

+0

删除我的评论 – Dheeraj

下面的代码可以解决你的问题:

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> 

代码:

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(); 
    } 

编辑#1(后用户的请求)

对于纯MVVM,你必须写一个附加行为。我已将所有的东西都放在MainWindow名称空间下。

用法:

<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> 

代码:

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; } 
} 
+0

是否有可能在MVVM中? – user2749679

+0

@ user2749679查看更新后的答案 – AnjumSKhan