WPF 可见性折叠保留空间
Posted
技术标签:
【中文标题】WPF 可见性折叠保留空间【英文标题】:WPF visibility collapse keep space 【发布时间】:2020-12-10 21:12:53 【问题描述】:我有 3 列,在使用特定转换器时,我成功地将中间列和右列的可见性更改为可见性折叠或可见。
我的问题是,当这些列应该可见时,我希望它们具有星号宽度,而折叠宽度必须为自动。
然后,如果它们的可见性可见,我的所有列都共享相同的空间,否则她将占据所有空间并且可以居中到父级。
我设置了我的可见性转换器
internal class TradeUnitLevelToVisibilityConverter : BaseConverter, IValueConverter
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
return value != null && (TradeUnit)value == TradeUnit.Unit
? Visibility.Collapsed
: Visibility.Visible;
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
return null;
我的宽度转换器
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
return value != null && (TradeUnit)value == TradeUnit.Unit
? new GridLength(0, GridUnitType.Auto)
: new GridLength(5, GridUnitType.Star);
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
return null;
我的 xaml :
<Grid Grid.Column="1" Background="StaticResource Black3C3D41Brush">
<Grid Grid.Column="1" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*"/>
<ColumnDefinition Width="2.5*"/>
<ColumnDefinition >
<!--<ColumnDefinition.Style>
<Style TargetType="ColumnDefinition">
<Setter Property="Width" Value="*"/>
<Style.Triggers>
<DataTrigger Binding="Binding , Converter=eshopeur:TradeUnitLevelToVisibilityConverter" Value="Unit">
<Setter Property="Width" Value="auto"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ColumnDefinition.Style>-->
</ColumnDefinition>
<ColumnDefinition >
<!--<ColumnDefinition.Style>
<Style TargetType="ColumnDefinition">
<Setter Property="Width" Value="2.5*"/>
<Style.Triggers>
<DataTrigger Binding="Binding , Converter=eshopeur:TradeUnitLevelToVisibilityConverter" Value="Collapsed">
<Setter Property="Width" Value="auto"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ColumnDefinition.Style>-->
</ColumnDefinition>
<ColumnDefinition Width="0.5*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="1" HorizontalAlignment="Center">
...
</Grid>
<Grid Grid.Column="2" Visibility="Binding UnitTradeUnitlevel,
Converter=eshopeur:TradeUnitLevelToVisibilityConverter"
HorizontalAlignment="Stretch"
Width="Binding UnitTradeUnitlevel, Converter=auxilaryscreen:UnitTradeUnitToVisibilityConverter" >
<Grid>
...
</Grid>
<Grid Grid.Column="3" HorizontalAlignment="Stretch"
Width="Binding UnitTradeUnitlevel, Converter=auxilaryscreen:UnitTradeUnitToVisibilityConverter"
Visibility="Binding UnitTradeUnitlevel, Converter=eshopeur:TradeUnitLevelToVisibilityConverter">
...
</Grid>
</Grid>
</Grid>
我尝试使用触发器,但我不知道如何正确设置它们,因为他们正在检查可见性转换器以适应宽度。
这是我所期望的 虽然都可见
all visible
折叠时
collapse
我的实际结果是崩溃:
today collapse result
你有什么办法可以同时改变列的可见性和宽度吗?
【问题讨论】:
用Visibility.Hidden
代替Visibility.Collapsed
怎么样?
.Hidden 也会保留列空间。如果我成功将列的宽度设置为 auto 而不是 * 当可见性折叠时,visibility.Collapse 将正确忽略空格。
您可以尝试使用 jagged arrays 布局:代替带有行和列的类似表格的顶部容器定义一个或多个列表,其中每一行是单元格的另一个容器。这将为您提供更大的灵活性(例如,您将能够通过折叠单元格来占据所有可用宽度),但现在您将遇到另一个问题:如何在行之间同步单元格宽度。
【参考方案1】:
最后我更改了我的 xaml 树和一个转换器:当一列可见时,另一列不可见,全部设置为 width = auto。
它似乎可以完成这项工作,如果我能找到更清洁的解决方案,那就太好了。如果有人已经用我感兴趣的触发器做到了。
【讨论】:
【参考方案2】:实现结果的一种方法是为列定义创建附加行为。
附加的行为是一个带有 3 个附加属性的静态类。您可以更改名称以使其真正有意义。
DefaultWidth - 列定义的默认宽度 UnitWidth - 当TradeUnit
为Unit
时列定义的宽度
TradeUnit - 贸易单位
当TradeUnit
更改时,行为会将列定义的Width
设置为正确的值DefaultWidth
或UnitWidth
。
using System.Windows;
using System.Windows.Controls;
namespace SO
public static class TradeUnitColumnWidthBehavior
#region DefaultWidth (Attached Property)
public static readonly DependencyProperty DefaultWidthProperty =
DependencyProperty.RegisterAttached(
"DefaultWidth",
typeof(GridLength),
typeof(TradeUnitColumnWidthBehavior),
new PropertyMetadata(null));
public static GridLength GetDefaultWidth(DependencyObject obj)
return (GridLength)obj.GetValue(DefaultWidthProperty);
public static void SetDefaultWidth(DependencyObject obj, GridLength value)
obj.SetValue(DefaultWidthProperty, value);
#endregion
#region UnitWidth (Attached Property)
public static readonly DependencyProperty UnitWidthProperty =
DependencyProperty.RegisterAttached(
"UnitWidth",
typeof(GridLength),
typeof(TradeUnitColumnWidthBehavior),
new PropertyMetadata(null));
public static GridLength GetUnitWidth(DependencyObject obj)
return (GridLength)obj.GetValue(UnitWidthProperty);
public static void SetUnitWidth(DependencyObject obj, GridLength value)
obj.SetValue(UnitWidthProperty, value);
#endregion
#region TradeUnit (Attached Property)
public static readonly DependencyProperty TradeUnitProperty =
DependencyProperty.RegisterAttached(
"TradeUnit",
typeof(MainWindowViewModel.TradeUnit),
typeof(TradeUnitColumnWidthBehavior),
new PropertyMetadata(MainWindowViewModel.TradeUnit.None, OnTradeUnitChanged));
public static MainWindowViewModel.TradeUnit GetTradeUnit(DependencyObject obj)
return (MainWindowViewModel.TradeUnit)obj.GetValue(TradeUnitProperty);
public static void SetTradeUnit(DependencyObject obj, MainWindowViewModel.TradeUnit value)
obj.SetValue(TradeUnitProperty, value);
private static void OnTradeUnitChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
var columnDefinition = (ColumnDefinition)d;
if (columnDefinition == null) return;
if ((MainWindowViewModel.TradeUnit) e.NewValue == MainWindowViewModel.TradeUnit.Unit)
columnDefinition.Width = GetUnitWidth(d);
else
columnDefinition.Width = GetDefaultWidth(d);
#endregion
这是 XAML 的一个示例:
<Grid ShowGridLines="True">
<!-- -->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="2.5*"
local:TradeUnitColumnWidthBehavior.DefaultWidth="2.5*"
local:TradeUnitColumnWidthBehavior.TradeUnit="Binding RelativeSource=RelativeSource AncestorType=x:Type Grid, Path=DataContext.UnitTradeUnitLevel"
local:TradeUnitColumnWidthBehavior.UnitWidth="*" />
<ColumnDefinition Width="1.5*"
local:TradeUnitColumnWidthBehavior.DefaultWidth="1.5*"
local:TradeUnitColumnWidthBehavior.TradeUnit="Binding RelativeSource=RelativeSource AncestorType=x:Type Grid, Path=DataContext.UnitTradeUnitLevel"
local:TradeUnitColumnWidthBehavior.UnitWidth="Auto" />
<ColumnDefinition Width="2.5*"
local:TradeUnitColumnWidthBehavior.DefaultWidth="2.5*"
local:TradeUnitColumnWidthBehavior.TradeUnit="Binding RelativeSource=RelativeSource AncestorType=x:Type Grid, Path=DataContext.UnitTradeUnitLevel"
local:TradeUnitColumnWidthBehavior.UnitWidth="Auto" />
<ColumnDefinition Width="0.5*" />
</Grid.ColumnDefinitions>
<Border x:Name="Border1"
Grid.Column="1"
Background="Red">
<Button
HorizontalAlignment="Center"
VerticalAlignment="Center"
Command="Binding TradeUnitCommand"
Content="Change Unit" />
</Border>
<Border
Grid.Column="2"
Background="Green"
Visibility="Binding UnitTradeUnitLevel, Converter=StaticResource TradeUnitLevelToVisibilityConverter" />
<Border
Grid.Column="3"
Background="Blue"
Visibility="Binding UnitTradeUnitLevel, Converter=StaticResource TradeUnitLevelToVisibilityConverter" />
</Grid>
【讨论】:
以上是关于WPF 可见性折叠保留空间的主要内容,如果未能解决你的问题,请参考以下文章