手动设置窗口位置wpf mvvm

时间:2016-07-14 12:36:32

标签: wpf mvvm

我正在使用带MVVM模式的WPF。

我想通过获取其他控件的坐标来设置新打开的说新窗口位置(左,顶部,宽度,高度),例如基本窗口上的边框说主窗口。 我在主窗口中使用以下代码:

<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按钮启动新窗口说新窗口。 启动新窗口不是问题,但我想将此窗口启动到与主窗口上的边框相同的位置。 新窗口应完全适合主窗口上的边框。

1 个答案:

答案 0 :(得分: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; }
}