2016-07-14 148 views
0

我正在使用帶有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

回答

1

下面的代碼可以解決你的問題:

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