Grid Splitter在对角线上工作?

时间:2014-12-08 21:49:29

标签: c# wpf gridsplitter

我正在尝试在其中放置一个透明方块的窗口,我希望允许用户以他/她想要的任何方式重新调整大小。此代码适用于垂直和水平重新调整大小

<Window x:Class="TransparentWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="PloofTAS" Height="355" Width="539" Topmost="True"
        ResizeMode="NoResize" 
        AllowsTransparency="True" 
        Background="Transparent"
        WindowStyle="None" MouseLeftButtonDown="Window_MouseLeftButtonDown">

    <Grid Name="GlobalGrid">
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="8" />
            <RowDefinition Height="*" />
            <RowDefinition Height="8" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="8" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="8" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Rectangle Fill="Gray" Grid.Column="0" Grid.RowSpan="5" />
        <Rectangle Fill="Gray" Grid.Column="4" Grid.RowSpan="5" />
        <Rectangle Fill="Gray" Grid.Column="1" Grid.Row="0" Grid.ColumnSpan="3" />
        <Rectangle Fill="Gray" Grid.Column="1" Grid.Row="4" Grid.ColumnSpan="3" />
        <GridSplitter Grid.Column="2" Grid.Row="1" Height="Auto" HorizontalAlignment="Stretch" />
        <GridSplitter Grid.Column="1" Grid.Row="2" Height="Auto" HorizontalAlignment="Stretch" />
        <GridSplitter Grid.Column="3" Grid.Row="2" Height="Auto" HorizontalAlignment="Stretch" />
        <GridSplitter Grid.Column="2" Grid.Row="3" Height="Auto" HorizontalAlignment="Stretch" />
        <Rectangle Fill="Orange" Grid.Row="1" Grid.Column="1" />
        <Rectangle Fill="Orange" Grid.Row="1" Grid.Column="3" />
        <Rectangle Fill="Orange" Grid.Row="3" Grid.Column="1" />
        <Rectangle Fill="Orange" Grid.Row="3" Grid.Column="3" />
        <Rectangle Fill="Transparent" Stroke="Red" Grid.Column="2" Grid.Row="2"/>
    </Grid>
</Window>

以下是生成的窗口

There is no need to compile the code ^_^

我希望橙色方块(红色/透明方块的角落)能够对角工作,或垂直和水平工作。有可能吗?

1 个答案:

答案 0 :(得分:1)

我不知道这个问题的优雅解决方案,因为无法以编程方式设置GridSplitter。

我的解决方案只是捕获脏鼠标,并根据鼠标移动设置列和行测量。

设置样式和事件。标记属性存储索引,我们将在后面的代码中更改行和列。

<Window.Resources>
    <Style x:Key="DiagonalSplitterRectangle" TargetType="{x:Type Rectangle}">
        <Setter Property="Fill" Value="Orange"/>
        <EventSetter Event="MouseDown" Handler="UIElement_OnMouseDown"/>
        <EventSetter Event="MouseMove" Handler="UIElement_OnMouseMove"/>
        <EventSetter Event="MouseUp" Handler="UIElement_OnMouseUp"/>
        <EventSetter Event="LostMouseCapture" Handler="UIElement_OnLostMouseCapture"/>
    </Style>
</Window.Resources>

    <Rectangle Grid.Row="1" Grid.Column="1" Style="{StaticResource DiagonalSplitterRectangle}" Tag="0,0"/>
    <Rectangle Grid.Row="1" Grid.Column="3" Style="{StaticResource DiagonalSplitterRectangle}" Tag="0,4"/>
    <Rectangle Grid.Row="3" Grid.Column="1" Style="{StaticResource DiagonalSplitterRectangle}" Tag="4,0"/>
    <Rectangle Grid.Row="3" Grid.Column="3" Style="{StaticResource DiagonalSplitterRectangle}" Tag="4,4"/>

简单的鼠标捕获事件:

    private bool _isMouseCaptured;

    public MainWindow()
    {
        InitializeComponent();
    }

    private void UIElement_OnMouseDown(object sender, MouseButtonEventArgs e)
    {
        var uiElement = sender as UIElement;
        if (uiElement == null)
            return;

        if (uiElement.CaptureMouse())
            _isMouseCaptured = true;
    }

    private void UIElement_OnMouseMove(object sender, MouseEventArgs e)
    {
        if (!_isMouseCaptured)
            return;

        var clientWindow = Content as FrameworkElement;
        if (clientWindow == null)
            return;

        var rectangle = sender as Rectangle;
        if (rectangle == null)
            return;

        Point position = Mouse.GetPosition(GlobalGrid); ;

        if (position.X < 0 || position.Y < 0 || position.X > clientWindow.ActualWidth || position.Y > clientWindow.ActualHeight)
            return;

        GridUpdate(position, rectangle, clientWindow);
    }

    private void UIElement_OnMouseUp(object sender, MouseButtonEventArgs e)
    {
        if (!_isMouseCaptured)
            return;

        var uiElement = sender as UIElement;
        if (uiElement == null)
            return;

        uiElement.ReleaseMouseCapture();
    }

    private void UIElement_OnLostMouseCapture(object sender, MouseEventArgs e)
    {
        _isMouseCaptured = false;
    }

根据存储在rectangle.Tag属性中的值调整网格列和行的大小。 为了正确行为,还需要更改相反的列和行度量。

    private void GridUpdate(Point position, Rectangle rectangle, FrameworkElement clientWindow)
    {
        var gridPosition = new GridPosition(rectangle.Tag.ToString());
        var oppositeGridPosition = GetOppositeGridPosition(gridPosition);

        var rowHeight = GetMeasure(gridPosition.Row, position.Y, clientWindow.ActualHeight);
        var columnWidth = GetMeasure(gridPosition.Column, position.X, clientWindow.ActualWidth);

        var oppositeRowHeight = GlobalGrid.RowDefinitions[oppositeGridPosition.Row].ActualHeight;
        var oppositeColumnWidth = GlobalGrid.ColumnDefinitions[oppositeGridPosition.Column].ActualWidth;

        GlobalGrid.RowDefinitions[gridPosition.Row].Height = new GridLength(rowHeight);
        GlobalGrid.ColumnDefinitions[gridPosition.Column].Width = new GridLength(columnWidth);

        GlobalGrid.RowDefinitions[oppositeGridPosition.Row].Height = new GridLength(oppositeRowHeight);
        GlobalGrid.ColumnDefinitions[oppositeGridPosition.Column].Width = new GridLength(oppositeColumnWidth);
    }

    private GridPosition GetOppositeGridPosition(GridPosition gridPosition)
    {
        var row = (gridPosition.Row == 0) ? 4 : 0;
        var column = (gridPosition.Column == 0) ? 4 : 0;

        return new GridPosition(row, column);
    }

    private double GetMeasure(int gridPosition, double position, double windowMeasure)
    {
        return gridPosition == 0 ? position : windowMeasure - position;
    }

GridPosition是存储列和行索引值的结构。

public struct GridPosition
{
    public int Row { get; private set; }
    public int Column { get; private set; }

    public GridPosition(int row, int column)
        : this()
    {
        Row = row;
        Column = column;
    }

    public GridPosition(string gridPostion)
        : this()
    {
        Row = Convert.ToInt32(gridPostion.Split(',')[0]);
        Column = Convert.ToInt32(gridPostion.Split(',')[1]);
    }
}