如何解决WPF可见性崩溃保留空间
我有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,System.Globalization.CultureInfo culture)
{
return null;
}
}
我的宽度转换器
public object Convert(object value,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,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>
我尝试使用触发器,但是我不知道如何正确设置它们,因为他们正在检查可见性转换器以适应宽度。
这是我期望的 而所有可见的
崩溃时
我的实际结果是崩溃:
您有什么解决方案可以同时更改列的可见性和宽度?
解决方法
获得结果的一种方法是为列定义创建附加行为。
附加行为是具有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",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),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>
,
最后我改变了我的xaml树和一个转换器:当一列可见时,另一列不可见,全部设置为width = auto。
这似乎可以完成工作,如果我可以找到更清洁的解决方案,那就太好了。如果有人已经用触发器完成了它,我就会对此感兴趣。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。