【问题标题】:grid column with sharedsizegroup does not 'reclaim' the size when it is collapsed or invisible具有 sharedsizegroup 的网格列在折叠或不可见时不会“回收”大小
【发布时间】:2021-12-03 05:47:37
【问题描述】:

我有以下 xaml:

<Window x:Class="SharedSizeGroupBug.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Window.Resources>

<StackPanel Grid.IsSharedSizeScope="True">
    <ToggleButton IsChecked="False" Name="TB" Content="Toggle" />

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" SharedSizeGroup="DZG" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>

        <TextBlock Text="A1" Width="100" />
        <TextBlock Text="A2" Grid.Column="1" />
    </Grid>

    <Grid Visibility="{Binding IsChecked, ElementName=TB, Converter={StaticResource BooleanToVisibilityConverter}}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" SharedSizeGroup="DZG" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>

        <TextBlock Text="B1" Width="200" />
        <TextBlock Text="B2" Grid.Column="1" />
    </Grid>
</StackPanel>
</Window>

当您尝试此操作时,第一列的初始状态为 100 宽。当按下按钮并且第二个网格可见时,第一列的宽度为 200。但是,当您再次按下该按钮时,该列仍将是 200 宽。

【问题讨论】:

  • 当你说“仍然是 100 宽”时,你的意思是它仍然是 200 宽吗?
  • 是的,我就是这个意思,已编辑
  • 是的,折叠时似乎不会重新测量列。但是当 Grid 的可见性设置为 hidden 时它会这样做。

标签: wpf xaml


【解决方案1】:

我遇到了同样的问题,但使用的是行而不是列。我终于用自定义的 ivalue 绑定转换器打败了它,并且基本上基于绑定可见性剥离/恢复共享大小的组。

这是转换器:

class VisibilityToSharedSizeGroupConverter : System.Windows.Data.IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (((System.Windows.Visibility)value) == System.Windows.Visibility.Visible) ? parameter : null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return System.Windows.Data.Binding.DoNothing;
    }
}

这是一个 XAML 示例:

<Window.Resources>
    <local:VisibilityToSharedSizeGroupConverter x:Key="VisToShared" />
</Window.Resources>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" 
                       SharedSizeGroup="{Binding Converter={StaticResource ResourceKey=VisToShared}, ConverterParameter='LabelsGroup', ElementName=MyLabel1, Path=Visibility}"/>
        </RowDefinition>
    </Grid.RowDefinitions>
</Grid>

【讨论】:

  • 非常感谢您发布解决方案。我现在有同样的问题。真的很讨厌 WPF...
  • @Konrad 出于好奇,您喜欢哪些 UI 框架?我个人认为 WPF 非常易于使用且开发速度非常快。
  • 我在值转换器中使用 null 而不是空字符串,因为当它处理空字符串时,它抱怨空字符串不是有效值。
  • @Clonkex 我只能分享我的个人观点,但是在使用了许多桌面(Qt、WPF、Sciter)和基于 web/HTML/js 的框架(React、Vue、Svelte、Angular)之后。我必须说,现有的桌面 UI 框架没有一个能比我使用 React 和 Svelte 的开发体验更好(Vue 也很好)。如今,如果我想创建一个桌面应用程序,我可能会使用 MAUI/Blazor 或只使用 Electron 。如果我想要更高的安全性,我会选择基于 Rust/C++ 的东西,因为 .NET 太容易进行逆向工程。
  • @Clonkex 我没有用 null 测试它,但如果它有效,请随时编辑我的答案。
【解决方案2】:

据我所知,Width="Auto" 不一定会随着项目的变化而更新宽度。

我相信我过去所做的是设置宽度= Double.NaN(或设置宽度=它自己的实际宽度然后将其设置为double.NaN)as per this post

我相信有人通过双击列边框的反射找到了这段代码,所以这实际上是微软在内部调整列大小的做法

您可以使用网格而不是视图来实现类似于该帖子的内容。您也可以将其直接放在切换的点击事件中(这也适用于 MVVM,因为代码纯粹为用户界面创建行为)

【讨论】:

  • 当网格内的内容调整大小并变小(或被删除)时,会正确重新计算共享大小组。我认为这来自 WPF 假设折叠元素没有大小并且不需要测量/排列的问题。
  • 是的,我认为这是因为 Column 的大小实际上并没有改变(它只是被隐藏),所以它不知道调整大小。你试过 Double.NaN 吗?
  • 我找到的唯一可行的解​​决方案是在 IsVisible 更改为 false 时从 ColumnDefintion 中删除 SharedSizeGroup 名称,并在再次显示网格时重置它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-14
  • 2018-09-26
  • 1970-01-01
相关资源
最近更新 更多