c# - Grid Splitter 在对角线上工作?

标签 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 ^_^

我希望橙色方 block (红色/透明方 block 的角)能够沿对角线或垂直和水平方向工作。可能吗?

最佳答案

我不知道这个问题的优雅解决方案,因为无法以编程方式设置 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]);
    }
}

关于c# - Grid Splitter 在对角线上工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27367624/

相关文章:

c# - 哪个更好更便宜 : class matching vs exception?

c# - EventAggregator 和 ServiceLocator 问题

wpf gridsplitter问题——两边都缩小

c# - WPF ListView 大数据时性能很差

当列宽 ="Auto"时,WPF GridSplitter 出现奇怪的行为

c# - 为什么这个数据绑定(bind)不改变 GridUnitType?

c# - 具有存储过程的 Visual Studio 数据集设计器?这个图标是什么

c# - try catch 在 WinForms 应用程序中无法正常工作

c# - Unity3d检测平面上的点击

c# - FatSecret C# 包装的 api 在 WPF 中返回空响应