【问题标题】:WPF - How to get only one expander expanded at any one timeWPF - 如何在任何时候只扩展一个扩展器
【发布时间】:2009-12-17 15:54:58
【问题描述】:

我有一个包含一组扩展器的 StackPanel,如何设置它以便在任何时候只扩展扩展器?

干杯

【问题讨论】:

标签: wpf stackpanel expander


【解决方案1】:

用户“Dabblernl”将此作为评论发布,但它值得成为一个答案,因为它是一个完美的仅限 XAML 的解决方案,可以很好地自定义并且没有任何黑客攻击。

想法是将 Expander 控件放置在 ListBox 中,并将 Expander.IsExpanded 属性绑定到 ListBoxItem.IsSelected 属性。

这是一个现成的示例,您可以将其粘贴到 XAML 文件中并试用:

<ListBox>
    <ListBox.Resources>
        <Style TargetType="{x:Type Expander}">
            <Setter Property="IsExpanded" Value="{Binding Path=IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}" />
        </Style>
    </ListBox.Resources>
    <ListBox.Template>
        <ControlTemplate TargetType="{x:Type ListBox}">
            <ItemsPresenter />
        </ControlTemplate>
    </ListBox.Template>
    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListBoxItem}">
                        <ContentPresenter Content="{TemplateBinding Content}" />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ListBox.ItemContainerStyle>
    <Expander Background="Gray" Width="243" Header="Expander1">
        <StackPanel>
            <RadioButton Content="Eat Me" GroupName="Two" />
            <RadioButton Content="Eat Pork" GroupName="Two" />
            <RadioButton Content="Eat at Joe's" GroupName="Two" />
        </StackPanel>
    </Expander>
    <Expander Background="Gray" Width="243" Header="Expander2">
        <StackPanel>
            <RadioButton Content="Pork" GroupName="Two" />
            <RadioButton Content="Beef" GroupName="Two" />
            <RadioButton Content="Chicken" GroupName="Two" />
        </StackPanel>
    </Expander>
    <Expander Background="Gray" Width="243" Header="Expander3">
        <StackPanel>
            <RadioButton Content="Grill" GroupName="Two" />
            <RadioButton Content="Bake" GroupName="Two" />
            <RadioButton Content="Fry" GroupName="Two" />
        </StackPanel>
    </Expander>
</ListBox>

这里曾经是: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=3061227&SiteID=1 但是 forums.microsoft.com 似乎已经破产了。

仍然可以在此页面上找到它: https://social.msdn.microsoft.com/Forums/en-US/a2988ae8-e7b8-4a62-a34f-b851aaf13886/windows-presentation-foundation-faq?forum=wpf 标题为“3.4 如何在一组扩展器控件中只打开一个扩展器控件?”

【讨论】:

    【解决方案2】:

    这是在 WPF 中执行此操作的更精细的方法,无需任何代码:

    <UserControl.Resources>
        <ResourceDictionary>
            ...
            <Style TargetType="{x:Type Expander}">
                <Setter Property="IsExpanded" Value="{Binding Path=IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}"/>
            </Style>
    
        </ResourceDictionary>
    
    </UserControl.Resources>
    
    <Grid x:Name="LayoutRoot" Background="{x:Null}" Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <ScrollViewer VerticalAlignment="Top" HorizontalAlignment="Stretch" VerticalScrollBarVisibility="Auto" VerticalContentAlignment="Top" BorderThickness="0,0,0,0" Grid.RowSpan="1" Grid.Row="0">
            <ListBox x:Name="OrdersListBox" BorderThickness="0" ItemContainerStyle="{StaticResource ShellThemeListBoxStyle}" 
                     IsSynchronizedWithCurrentItem="True" 
                     prism:RegionManager.RegionName="{x:Static uiCommon:RegionNames.WorkSheetsRegion}" Background="#00000000">
                <ListBox.ItemTemplate>
                    <DataTemplate DataType="typeData:WorkSheetsDetialsViewModel">
                        <local:WorkSheetsDetialsView/>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </ScrollViewer>
        ...
    </Grid>
    
    <UserControl 
        x:Class="Module.ExcelDocumentManager.WorkSheets.WorkSheetsDetialsView"
        ...>
        <Expander>
            <Expander.Header>
                <TextBlock Text="{Binding HeaderInfo}" RenderTransformOrigin=".5,.5">
                </TextBlock>
            </Expander.Header>
            ...
    
        </Expander>
    </UserControl>
    

    【讨论】:

      【解决方案3】:

      我真的不想这样做,因为它需要将代码 (C#) 放在窗口的文件后面的类中(我试图通过使用 ViewModel 等来完全避免这种情况)。

      理想情况下,我会在 XAML 中对此进行描述。

      我连接了我感兴趣的每个 Expander 'Expanded' 事件并执行了以下操作:

          private void HandleExpanderExpanded(object sender, RoutedEventArgs e)
          {
              ExpandExculsively(sender as Expander);
          }
      
          private void ExpandExculsively(Expander expander)
          {
              foreach (var child in findPanel.Children)
              {
                  if (child is Expander && child != expander)
                      ((Expander)child).IsExpanded = false;
              }
          }
      

      干杯

      AWC

      【讨论】:

      • 所以,这就是您在 WinForms 等老式框架中的做法。但是,它不是“WPF 方式”,因为要使 WPF 完全健壮,您希望从数据而不是事件中派生状态。
      • 我意识到这一点,因此我的 cmets,但我对后面的代码中的这一点很满意
      • 是的,你总是可以把它放在一个列表框中——嘘——你的方式要好得多——它不是 WPF 方式,而是.. 做错了使其成为 WPF 方式也不正确! social.msdn.microsoft.com/Forums/vstudio/en-US/…
      【解决方案4】:

      您可以添加一个值为“展开的扩展器”的依赖属性,然后您可以使用您最喜欢的表达式绑定技术(类型转换器等)将“展开”属性绑定到表达式“theExpandedProperty == this” )。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-28
        • 1970-01-01
        • 2021-08-10
        • 2013-06-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多