使用 SharedSizeGroup 测量/排列网格

发布于 2024-09-27 00:35:28 字数 7405 浏览 7 评论 0原文

两个包含以某种方式指定的元素的网格和 SharedSizeGroup 似乎存在一些问题。

这个问题是为了回应 之前的问题来自用户DH,我试图回答。请原谅它的长度,但它有助于直观地展示问题。

他最初的问题是,为什么在满足某些条件(调整右侧网格中的 TextBlock 的大小)时,具有 SharedSizeGroup 的两个网格没有调整到相同的高度。我采用了他的例子并对其进行了扩展,因为我怀疑它与测量/安排周期有关。

事实证明,它确实与“测量和安排”有关。实际上,这与没有进行测量有关。 我觉得这至少是一个问题,即使不是一个错误,但我想对此行为进行解释。

以下是所发生情况的快速概述(花哨的颜色仅用于演示目的) .

启动
两个网格都有三行,每行包含一个 TextBlock。中间行是 SharedSizeGroup。中间行的文本绑定到其 TextBlock 的 ActualHeight,初始 Height 属性硬编码为您看到的值。网格下方的数字代表该网格的实际高度。请注意,左侧网格的背景颜色为绿色。

Startup

增加右侧 TextBlock
当右侧网格的大小增加时,您可以看到两个网格由于 SharedSizeGroup 的原因都调整到了新的高度。右侧的列反映了网格的测量和排列调用。

尺寸增加

减小右侧 TextBlock,但仍大于左侧 TextBlock
当右侧网格的大小减小,但仍然大于左侧硬编码 TextBlock 的大小时,您可以看到,由于 SharedSizeGroup,两个网格再次调整到新的高度。右侧的列反映了网格的测量和排列调用。

减小到最小大小

将右侧文本块减小到小于左侧文本块的大小< br> 当右侧网格的大小减小到小于左侧硬编码 TextBlock 的大小时,您可以看到左侧网格没有减小到“正确”的大小,如以下所示底部网格的绿色背景,以及网格的大小是 150,而不是 130。

如果您查看右侧的信息,您会注意到左侧网格做了排列,但没有不进行测量。

Decreased Past Size


以下是重复问题的示例代码。

InfoGrid 和 InfoGridEventArgs 类

using System.Windows;
using System.Windows.Controls;
namespace GridMeasureExample
{
    class InfoGrid : Grid
    {
        protected override Size ArrangeOverride(Size arrangeSize)
        {
            CallReportInfoEvent("Arrange");
            return base.ArrangeOverride(arrangeSize);
        }
        protected override Size MeasureOverride(Size constraint)
        {
            CallReportInfoEvent("Measure");
            return base.MeasureOverride(constraint);
        }
        public event EventHandler<InfoGridEventArgs> ReportInfo;
        private void CallReportInfoEvent(string message)
        {
            if (ReportInfo != null)
                ReportInfo(this, new InfoGridEventArgs(message));
        }
    }
    public class InfoGridEventArgs : EventArgs
    {
        private InfoGridEventArgs()
        {
        }
        public InfoGridEventArgs(string message)
        {
            this.TimeStamp = DateTime.Now;
            this.Message = message;
        }
        public DateTime TimeStamp
        {
            get;
            private set;
        }
        public String Message
        {
            get;
            private set;
        }
    }
}

主窗口 XAML

<Window x:Class="GridMeasureExample.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:GridMeasureExample"
        Title="SharedSizeGroup" Height="500" Width="500">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <StackPanel Grid.Column="0" 
                    Grid.Row="0"
                    Orientation="Horizontal" 
                    HorizontalAlignment="Left"
                    VerticalAlignment="Top"
                    Grid.IsSharedSizeScope="True">

            <StackPanel Orientation="Vertical" Width="100">
                <local:InfoGrid x:Name="grid1" Background="Green" ShowGridLines="True">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="15" />
                        <RowDefinition SharedSizeGroup="Group1" />
                        <RowDefinition Height="15" />
                    </Grid.RowDefinitions>
                    <TextBlock Background="Blue" Grid.Row="0" Text="Row 0"/>
                    <TextBlock Background="Red" Grid.Row="1" Name="textBlock1" Height="100"
                           Text="{Binding RelativeSource={RelativeSource Self}, Path=ActualHeight}"/>
                    <TextBlock Background="Blue" Grid.Row="2" Text="Row 2" />
                </local:InfoGrid>
                <TextBlock Text="{Binding Path=ActualHeight, ElementName=grid1}" />
            </StackPanel>

            <StackPanel Orientation="Vertical" Width="100">
                <local:InfoGrid x:Name="grid2" Background="Yellow" ShowGridLines="True">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="15" />
                        <RowDefinition SharedSizeGroup="Group1" />
                        <RowDefinition Height="15" />
                    </Grid.RowDefinitions>
                    <TextBlock Background="Orange" Grid.Row="0" Text="Row 0" />
                    <TextBlock Background="Purple" Grid.Row="1" Name="textBlock2" Height="150"
                           Text="{Binding RelativeSource={RelativeSource Self}, Path=ActualHeight}"/>
                    <TextBlock Background="Orange" Grid.Row="2" Text="Row 2" />
                </local:InfoGrid>
                <TextBlock Text="{Binding Path=ActualHeight, ElementName=grid2}" />
            </StackPanel>

        </StackPanel>

        <ListBox x:Name="lstInfo"
                 Grid.Column="1"
                 Grid.Row="0"
                 Margin="10,0,0,0"
                 HorizontalAlignment="Stretch"
                 VerticalAlignment="Stretch" />

        <UniformGrid Grid.Column="0"
                     Grid.Row="1"
                     Grid.ColumnSpan="2"
                     Columns="2"
                     HorizontalAlignment="Center"
                     Margin="5">
            <Button x:Name="btnIncrease" Margin="4,0">Increase</Button>
            <Button x:Name="btnDecrease" Margin="4,0">Decrease</Button>
        </UniformGrid>

    </Grid>

</Window>

主窗口构造函数(仅代码隐藏中的代码)

public Window1() { 初始化组件();

    btnIncrease.Click += (s, e) => 
        {
            lstInfo.Items.Add(String.Format("{0} Increase Button Pressed", DateTime.Now.ToString("HH:mm:ss.ffff")));
            textBlock2.Height += 30;
        };
    btnDecrease.Click += (s, e) =>
        {
            lstInfo.Items.Add(String.Format("{0} Decrease Button Pressed", DateTime.Now.ToString("HH:mm:ss.ffff")));
            if (textBlock2.ActualHeight >= 30)
                textBlock2.Height -= 30;
        };

    grid1.ReportInfo += (s, e) => lstInfo.Items.Add(String.Format("{0} Left Grid: {1}", e.TimeStamp.ToString("HH:mm:ss.ffff"), e.Message));
    grid2.ReportInfo += (s, e) => lstInfo.Items.Add(String.Format("{0} Right Grid: {1}", e.TimeStamp.ToString("HH:mm:ss.ffff"), e.Message));
}

There seems to be a bit of an issue with two grids containing elements specified in a certain way, and the SharedSizeGroup.

This question is in response to an earlier question from user D.H. I attempted to answer. Forgive the length, but it helps to demonstrate the problem visually.

His original question asked why two grids with a SharedSizeGroup didn't resize to the same height when certain conditions were met (resizing a TextBlock in the right-side grid). I took his example and expanded it, because I suspected that it had to do with the Measure/Arrange cycle.

It turns out that it does, in fact, have to do with Measure and Arrange. Actually, it has to do with not doing a Measure. I feel that this may be at least an issue, if not a bug, but would like to have an explanation of the behavior.

Here is a quick overview of what happens (garish colors for demo purposes only).

Start Up
Both grids have three rows, each containing a TextBlock. The middle row is of SharedSizeGroup. The text of the middle row is bound to the ActualHeight of its TextBlock, with the initial Height property hard-coded to the values you see. The numbers below the grids represent the ActualHeight of that grid. Note that the BackgroundColor of the left grid is Green.

Startup

Increasing the Right-Side TextBlock
When the right-side grid is increased in size, you can see that both grids resize to the new height, due to the SharedSizeGroup. The column at the right reflects the Measure and Arrange calls of the grids.

Increased In Size

Decreasing the Right-Side TextBlock But Still Greater Than Left-Side TextBlock
When the right-side grid is decreased in size, but still larger than the size of the hard-coded TextBlock of the left side, you can see that both grids again resize to the new height, due to the SharedSizeGroup. The column at the right reflects the Measure and Arrange calls of the grids.

Decreased to Minimum Size

Decreasing the Right-Side TextBlock Less Than Size of Left-Side TextBlock
When the right-side grid is decreased in size, less than the size of the hard-coded TextBlock of the left side, you can see that the left-side grid does not decrease to the "proper" size, as evidenced by seeing the Green background of the grid at the bottom, and the fact that the size of the grid is 150, not 130.

If you look at the info on the right, you will notice that the Left grid did an Arrange, but did not do a Measure.

Decreased Past Size


Here is the example code to duplicate the issue.

InfoGrid and InfoGridEventArgs classes

using System.Windows;
using System.Windows.Controls;
namespace GridMeasureExample
{
    class InfoGrid : Grid
    {
        protected override Size ArrangeOverride(Size arrangeSize)
        {
            CallReportInfoEvent("Arrange");
            return base.ArrangeOverride(arrangeSize);
        }
        protected override Size MeasureOverride(Size constraint)
        {
            CallReportInfoEvent("Measure");
            return base.MeasureOverride(constraint);
        }
        public event EventHandler<InfoGridEventArgs> ReportInfo;
        private void CallReportInfoEvent(string message)
        {
            if (ReportInfo != null)
                ReportInfo(this, new InfoGridEventArgs(message));
        }
    }
    public class InfoGridEventArgs : EventArgs
    {
        private InfoGridEventArgs()
        {
        }
        public InfoGridEventArgs(string message)
        {
            this.TimeStamp = DateTime.Now;
            this.Message = message;
        }
        public DateTime TimeStamp
        {
            get;
            private set;
        }
        public String Message
        {
            get;
            private set;
        }
    }
}

Main Window XAML

<Window x:Class="GridMeasureExample.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:GridMeasureExample"
        Title="SharedSizeGroup" Height="500" Width="500">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <StackPanel Grid.Column="0" 
                    Grid.Row="0"
                    Orientation="Horizontal" 
                    HorizontalAlignment="Left"
                    VerticalAlignment="Top"
                    Grid.IsSharedSizeScope="True">

            <StackPanel Orientation="Vertical" Width="100">
                <local:InfoGrid x:Name="grid1" Background="Green" ShowGridLines="True">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="15" />
                        <RowDefinition SharedSizeGroup="Group1" />
                        <RowDefinition Height="15" />
                    </Grid.RowDefinitions>
                    <TextBlock Background="Blue" Grid.Row="0" Text="Row 0"/>
                    <TextBlock Background="Red" Grid.Row="1" Name="textBlock1" Height="100"
                           Text="{Binding RelativeSource={RelativeSource Self}, Path=ActualHeight}"/>
                    <TextBlock Background="Blue" Grid.Row="2" Text="Row 2" />
                </local:InfoGrid>
                <TextBlock Text="{Binding Path=ActualHeight, ElementName=grid1}" />
            </StackPanel>

            <StackPanel Orientation="Vertical" Width="100">
                <local:InfoGrid x:Name="grid2" Background="Yellow" ShowGridLines="True">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="15" />
                        <RowDefinition SharedSizeGroup="Group1" />
                        <RowDefinition Height="15" />
                    </Grid.RowDefinitions>
                    <TextBlock Background="Orange" Grid.Row="0" Text="Row 0" />
                    <TextBlock Background="Purple" Grid.Row="1" Name="textBlock2" Height="150"
                           Text="{Binding RelativeSource={RelativeSource Self}, Path=ActualHeight}"/>
                    <TextBlock Background="Orange" Grid.Row="2" Text="Row 2" />
                </local:InfoGrid>
                <TextBlock Text="{Binding Path=ActualHeight, ElementName=grid2}" />
            </StackPanel>

        </StackPanel>

        <ListBox x:Name="lstInfo"
                 Grid.Column="1"
                 Grid.Row="0"
                 Margin="10,0,0,0"
                 HorizontalAlignment="Stretch"
                 VerticalAlignment="Stretch" />

        <UniformGrid Grid.Column="0"
                     Grid.Row="1"
                     Grid.ColumnSpan="2"
                     Columns="2"
                     HorizontalAlignment="Center"
                     Margin="5">
            <Button x:Name="btnIncrease" Margin="4,0">Increase</Button>
            <Button x:Name="btnDecrease" Margin="4,0">Decrease</Button>
        </UniformGrid>

    </Grid>

</Window>

Main Window Constructor (only code in code-behind)

public Window1()
{
InitializeComponent();

    btnIncrease.Click += (s, e) => 
        {
            lstInfo.Items.Add(String.Format("{0} Increase Button Pressed", DateTime.Now.ToString("HH:mm:ss.ffff")));
            textBlock2.Height += 30;
        };
    btnDecrease.Click += (s, e) =>
        {
            lstInfo.Items.Add(String.Format("{0} Decrease Button Pressed", DateTime.Now.ToString("HH:mm:ss.ffff")));
            if (textBlock2.ActualHeight >= 30)
                textBlock2.Height -= 30;
        };

    grid1.ReportInfo += (s, e) => lstInfo.Items.Add(String.Format("{0} Left Grid: {1}", e.TimeStamp.ToString("HH:mm:ss.ffff"), e.Message));
    grid2.ReportInfo += (s, e) => lstInfo.Items.Add(String.Format("{0} Right Grid: {1}", e.TimeStamp.ToString("HH:mm:ss.ffff"), e.Message));
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

丑丑阿 2024-10-04 00:35:28

根据 Microsoft,这是一个错误。

这似乎是 WPF 中的一个错误,并且
微软已经意识到这一点并且
研究解决方案。

如果您需要解决方法方面的帮助,
请联系 Microsoft 支持:

http://support.microsoft.com/default。 aspx?id=fh;en-us;offerprophone

您还可以提交错误反馈
WPF 关于此问题的信息位于...

http://connect.microsoft.com/VisualStudio

我已将其提交为Connect 网站

According to Microsoft, it's a bug.

This appears to be a bug in WPF, and
Microsoft is aware of it and
investigating a solution.

If you need help with a workaround,
please contact Microsoft Support at

http://support.microsoft.com/default.aspx?id=fh;en-us;offerprophone

You can also submit bug feedback for
WPF regarding this issue at…

http://connect.microsoft.com/VisualStudio

I've submitted this as a bug on the Connect site.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文