如何使用 DataTrigger 更改 ItemsControl 中的 ItemsPanel?

Posted

技术标签:

【中文标题】如何使用 DataTrigger 更改 ItemsControl 中的 ItemsPanel?【英文标题】:How to change ItemsPanel in ItemsControl with DataTrigger? 【发布时间】:2021-11-22 09:07:18 【问题描述】:

我试图制作一个包含多个元素的 UserControl,当单击按钮时,控件将内部元素布局从垂直更改为水平。

我在 ItemsControl 模板中放置了一个更改布局的 ToggleButton。我还创建了一个带有触发器的样式,它应该通过更改 ItemsControl 中的 ItemsPanel 来更改项目的位置。此外,触发器会更改 ItemsControl 的背景。

<ItemsControl.Template>
  <ControlTemplate TargetType="ItemsControl">
     <Grid>
        <Grid.Style>
            <Style TargetType="Grid">
                <Style.Triggers>
                    <DataTrigger Binding="Binding ElementName=HideShowButton, Path=IsChecked" Value="True">
                        <DataTrigger.Setters>
                            <Setter Property="ItemsControl.Background" Value="LightGreen"/>
                            <Setter Property="ItemsControl.ItemsPanel" Value="DynamicResource HorizontalPanelTemplate"/>
                        </DataTrigger.Setters>
                    </DataTrigger>

                    <DataTrigger Binding="Binding ElementName=HideShowButton, Path=IsChecked" Value="False">
                        <DataTrigger.Setters>
                            <Setter Property="ItemsControl.Background" Value="LightBlue"/>
                            <Setter Property="ItemsControl.ItemsPanel" Value="DynamicResource VerticalPanelTemplate"/>
                        </DataTrigger.Setters>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Grid.Style>

        <Grid.RowDefinitions>
            <RowDefinition x:Name="HeaderRow" Height="*"/>
            <RowDefinition x:Name="ToggleRow" Height="50"/>
        </Grid.RowDefinitions>

        <ItemsPresenter x:Name="ItemsPresenter" Grid.Row="0"/>

        <ToggleButton x:Name="HideShowButton" Grid.Row="1"
                                      Content="Change"
                                      VerticalAlignment="Center" HorizontalAlignment="Right"
                                      Margin="5"/>
     </Grid>
  </ControlTemplate>
</ItemsControl.Template>

因此,触发器起作用,颜色切换,但元素的排列始终保持不变。

我尝试按照文章中所述通过 GroupStyle 进行操作:https://social.msdn.microsoft.com/Forums/vstudio/en-US/b0ecb187-134e-4868-b56e-b67fb5ad18ff/itemscontrol-with-groupstyle-how-to-dynamically-switch-itemspanel?forum=wpf 但失败了,外观没有改变。

完整的用户控制代码

    <UserControl x:Class="HeaderControlDemo.HeaderControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <UserControl.Template>
        <ControlTemplate>
            <ItemsControl x:Name="ItemsControl" Margin="TemplateBinding Padding"
                          ItemsSource="Binding Path=HeaderItems">
                <ItemsControl.Resources>
                    <ItemsPanelTemplate x:Key="HorizontalPanelTemplate">
                        <StackPanel Orientation="Horizontal"/>
                    </ItemsPanelTemplate>

                    <ItemsPanelTemplate x:Key="VerticalPanelTemplate">
                        <StackPanel Orientation="Vertical"/>
                    </ItemsPanelTemplate>
                </ItemsControl.Resources>

                <ItemsControl.Template>
                    <ControlTemplate TargetType="ItemsControl">
                        <Grid>
                            <Grid.Style>
                                <Style TargetType="Grid">
                                    <Style.Triggers>
                                        <DataTrigger Binding="Binding ElementName=HideShowButton, Path=IsChecked" Value="True">
                                            <DataTrigger.Setters>
                                                <Setter Property="ItemsControl.Background" Value="LightGreen"/>
                                                <Setter Property="ItemsControl.ItemsPanel" Value="DynamicResource HorizontalPanelTemplate"/>
                                            </DataTrigger.Setters>
                                        </DataTrigger>

                                        <DataTrigger Binding="Binding ElementName=HideShowButton, Path=IsChecked" Value="False">
                                            <DataTrigger.Setters>
                                                <Setter Property="ItemsControl.Background" Value="LightBlue"/>
                                                <Setter Property="ItemsControl.ItemsPanel" Value="DynamicResource VerticalPanelTemplate"/>
                                            </DataTrigger.Setters>
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </Grid.Style>

                            <Grid.RowDefinitions>
                                <RowDefinition x:Name="HeaderRow" Height="*"/>
                                <RowDefinition x:Name="ToggleRow" Height="50"/>
                            </Grid.RowDefinitions>

                            <ItemsPresenter x:Name="ItemsPresenter" Grid.Row="0"/>

                            <ToggleButton x:Name="HideShowButton" Grid.Row="1"
                                          Content="Change"
                                          VerticalAlignment="Center" HorizontalAlignment="Right"
                                          Margin="5"/>
                        </Grid>
                    </ControlTemplate>
                </ItemsControl.Template>

                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Grid VerticalAlignment="Top" HorizontalAlignment="Left"
                              Background="Gray">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="30"/>
                                <RowDefinition Height="*"/>
                            </Grid.RowDefinitions>

                            <TextBlock Grid.Row="0" 
                                       HorizontalAlignment="Center" VerticalAlignment="Center"
                                       Text="Header"/>
                            <Border Grid.Row="1" 
                                    HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                                    Padding="5"
                                    Background="LightGray">
                                <ContentControl>
                                    <ContentControl.ContentTemplate>
                                        <DataTemplate>
                                            <TextBox DataContext="Binding RelativeSource=RelativeSource AncestorType=ContentControl, Path=DataContext" 
                                                     Text="Binding Path=PropertyValue, UpdateSourceTrigger=PropertyChanged"
                                                     FontSize="Binding RelativeSource=RelativeSource AncestorType=UserControl, Path=FontSize"
                                                     FontFamily="Binding RelativeSource=RelativeSource AncestorType=UserControl, Path=FontFamily"
                                                     VerticalAlignment="Top"
                                                     Background="White"/>
                                        </DataTemplate>
                                    </ContentControl.ContentTemplate>
                                </ContentControl>
                            </Border>
                        </Grid>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </ControlTemplate>
    </UserControl.Template>
</UserControl>

【问题讨论】:

【参考方案1】:

您可以使用 DataTrigger 更改用作 ItemsPanel 的 StackPanel 的方向:

<ItemsControl ItemsSource="Binding">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel>
                <StackPanel.Style>
                    <Style TargetType="StackPanel">
                        <Style.Triggers>
                            <DataTrigger
                                Binding="Binding IsChecked, ElementName=tb"
                                Value="True">
                                <Setter Property="Orientation" Value="Horizontal"/>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </StackPanel.Style>
            </StackPanel>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

<ToggleButton x:Name="tb" Content=" Horizontal "/>

【讨论】:

以上是关于如何使用 DataTrigger 更改 ItemsControl 中的 ItemsPanel?的主要内容,如果未能解决你的问题,请参考以下文章

使用 DataTrigger 以样式绑定到 Self

Datatrigger 适当地改变了 TextBlock 的初始属性,但不是在对象改变之后

如何使用 Binding="Binding" 以编程方式创建 DataTrigger?

如何将触发器与 SourceName 和 DataTrigger 结合使用?

绑定到 DataContext 的 WPF 样式 DataTrigger 不起作用

WPF - 如何结合 DataTrigger 和 Trigger?