我想要一个控件,其行为如下:
它必须使用这些精确控件(网格/扩展器),而不是一些自定义控件,因此我的应用程序的样式可以自动应用于它们。
我似乎无法找到已经制作的东西,似乎没有内置的解决方案(如果只有#34;填充" StackPanel ......)并且我能来的唯一解决方案最好是制作我自己的Grid实现,这似乎......令人生畏。
是否有找到或实施此类控制的解决方案?
这就是我现在所拥有的。它没有处理"单扩展"也不是填充物。我不知道StackPanel或Expander是否应该为此负责。
<ItemsControl>
<ItemsControl.Resources>
<DataTemplate x:Key="verticalHeader">
<ItemsControl ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type Expander}}, Path=Header}" />
</DataTemplate>
<Style TargetType="{x:Type Expander}"
BasedOn="{StaticResource {x:Type Expander}}">
<Setter Property="HeaderTemplate"
Value="{StaticResource verticalHeader}" />
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="ExpandDirection"
Value="Right" />
</Style>
</ItemsControl.Resources>
<ItemsControl.Template>
<ControlTemplate>
<!-- Damn you, StackPanel! -->
<StackPanel Orientation="Horizontal" IsItemsHost="True"/>
</ControlTemplate>
</ItemsControl.Template>
<Expander Header="Exp1">
<TextBlock Text="111111111" Background="Red"/>
</Expander>
<Expander Header="Exp2">
<TextBlock Text="222222222" Background="Blue"/>
</Expander>
<Expander Header="Exp3">
<TextBlock Text="333333333" Background="Green"/>
</Expander>
</ItemsControl>
答案 0 :(得分:1)
我的第一个想法是用行为执行此类操作。这是您可以添加到现有XAML控件的一些功能,可以为您提供一些额外的自定义。
我只看了一些没有使用ItemsSource的东西,因为我使用的是Grid with Columns等。但是在一个普通的网格中,你可以添加一个倾听它的行为&#39 ; s孩子们的扩展和倒塌事件是这样的:
public class ExpanderBehavior : Behavior<Grid>
{
private List<Expander> childExpanders = new List<Expander>();
protected override void OnAttached()
{
//since we are accessing it's children, we have to wait until initialise is complete for it's children to be added
AssociatedObject.Initialized += (gridOvject, e) =>
{
foreach (Expander expander in AssociatedObject.Children)
{
//store this so we can quickly contract other expanders (though we could just access Children again)
childExpanders.Add(expander);
//track expanded events
expander.Expanded += (expanderObject, e2) =>
{
//contract all other expanders
foreach (Expander otherExpander in childExpanders)
{
if (expander != otherExpander && otherExpander.IsExpanded)
{
otherExpander.IsExpanded = false;
}
}
//set width to star for the correct column
int index = Grid.GetColum(expanderObject as Expander);
AssociatedObject.ColumnDefinitions[index].Width = new GridLength(1, GridUnitType.Star);
};
//track Collapsed events
expander.Collapsed += (o2, e2) =>
{
//reset all to auto
foreach (ColumnDefinition colDef in AssociatedObject.ColumnDefinitions)
{
colDef.Width = GridLength.Auto;
}
};
}
};
}
}
像这样使用它,请注意您必须添加System.Windows.Interactivity作为项目的参考:
<Window ...
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:local="...">
<Window.Resources>
<DataTemplate x:Key="verticalHeader">
<ItemsControl ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type Expander}}, Path=Header}" />
</DataTemplate>
<Style TargetType="{x:Type Expander}"
BasedOn="{StaticResource {x:Type Expander}}">
<Setter Property="HeaderTemplate"
Value="{StaticResource verticalHeader}" />
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="ExpandDirection"
Value="Right" />
</Style>
<local:ExpanderBehavior x:Key="ExpanderBehavor"/>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<i:Interaction.Behaviors>
<local:ExpanderBehavior/>
</i:Interaction.Behaviors>
<Expander Header="Exp1">
<TextBlock Text="111111111" Background="Red"/>
</Expander>
<Expander Header="Exp2" Grid.Column="1">
<TextBlock Text="222222222" Background="Blue"/>
</Expander>
<Expander Header="Exp3" Grid.Column="2">
<TextBlock Text="333333333" Background="Green"/>
</Expander>
</Grid>
</Window>
最终结果:
编辑:使用ItemsControl - 将其添加到托管项目的网格中,并添加一点来管理列映射
public class ItemsSourceExpanderBehavior : Behavior<Grid>
{
private List<Expander> childExpanders = new List<Expander>();
protected override void OnAttached()
{
AssociatedObject.Initialized += (gridOvject, e) =>
{
//since we are accessing it's children, we have to wait until initialise is complete for it's children to be added
for (int i = 0; i < AssociatedObject.Children.Count; i++)
{
Expander expander = AssociatedObject.Children[i] as Expander;
//sort out the grid columns
AssociatedObject.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
Grid.SetColumn(expander, i);
childExpanders.Add(expander);
//track expanded events
expander.Expanded += (expanderObject, e2) =>
{
foreach (Expander otherExpander in childExpanders)
{
if (expander != otherExpander && otherExpander.IsExpanded)
{
otherExpander.IsExpanded = false;
}
}
//set width to auto
int index = AssociatedObject.Children.IndexOf(expanderObject as Expander);
AssociatedObject.ColumnDefinitions[index].Width = new GridLength(1, GridUnitType.Star);
};
//track Collapsed events
expander.Collapsed += (o2, e2) =>
{
foreach (ColumnDefinition colDef in AssociatedObject.ColumnDefinitions)
{
colDef.Width = GridLength.Auto;
}
};
}
};
}
}
用于:
<ItemsControl>
<ItemsControl.Template>
<ControlTemplate>
<Grid IsItemsHost="True">
<i:Interaction.Behaviors>
<local:ItemsSourceExpanderBehavior/>
</i:Interaction.Behaviors>
</Grid>
</ControlTemplate>
</ItemsControl.Template>
<Expander Header="Exp1">
<TextBlock Text="111111111" Background="Red"/>
</Expander>
<Expander Header="Exp2">
<TextBlock Text="222222222" Background="Blue"/>
</Expander>
<Expander Header="Exp3">
<TextBlock Text="333333333" Background="Green"/>
</Expander>
</ItemsControl>
注意,如果您对ItemsSource有任何更改,您必须添加一些逻辑来管理新的/删除的子项!