You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF布局控件中实现Accordion左侧停靠及选中切换布局组填充空间

实现Accordion左侧停靠+选中项切换LayoutGroup显示的布局方案

我帮你梳理了实现这个需求的具体方案,用DevExpress的控件可以轻松搞定,下面是详细的步骤和代码示例:

核心思路

把Accordion固定在左侧,通过监听它的选中项,动态控制右侧三个LayoutGroup的显示/隐藏,让选中项对应的Group自动填充剩余空间。

方案一:用DockLayoutManager(推荐)

DevExpress的DockLayoutManager是专门管理停靠布局的控件,能完美实现左侧停靠、右侧自动填充的效果,代码如下:

<!-- 先引入DevExpress命名空间:xmlns:dxdo="http://schemas.devexpress.com/winfx/2008/xaml/docking" xmlns:dxa="http://schemas.devexpress.com/winfx/2008/xaml/accordion" xmlns:dxlc="http://schemas.devexpress.com/winfx/2008/xaml/layoutcontrol" -->
<dxdo:DockLayoutManager>
    <dxdo:LayoutGroup Orientation="Horizontal">
        <!-- 左侧停靠的Accordion,固定宽度200 -->
        <dxdo:LayoutPanel DockWidth="200" Caption="导航">
            <dxa:AccordionControl x:Name="mainAccordion" 
                                  SelectionMode="Single">
                <dxa:AccordionItem Header="标签1" Tag="myTag1"/>
                <dxa:AccordionItem Header="标签2" Tag="myTag2"/>
                <dxa:AccordionItem Header="标签3" Tag="myTag3"/>
            </dxa:AccordionControl>
        </dxdo:LayoutPanel>
        
        <!-- 右侧动态内容区域,自动填充剩余空间 -->
        <dxdo:LayoutPanel>
            <dxlc:LayoutControl>
                <dxlc:LayoutGroup x:Name="myTag1" Header="LayoutGroup 1" 
                                 Visibility="{Binding ElementName=mainAccordion, Path=SelectedItem.Tag, Converter={local:TagToVisibilityConverter}, ConverterParameter=myTag1}">
                    <!-- 这里放你的组内内容 -->
                </dxlc:LayoutGroup>
                <dxlc:LayoutGroup x:Name="myTag2" Header="LayoutGroup 2" 
                                 Visibility="{Binding ElementName=mainAccordion, Path=SelectedItem.Tag, Converter={local:TagToVisibilityConverter}, ConverterParameter=myTag2}">
                    <!-- 这里放你的组内内容 -->
                </dxlc:LayoutGroup>
                <dxlc:LayoutGroup x:Name="myTag3" Header="LayoutGroup 3" 
                                 Visibility="{Binding ElementName=mainAccordion, Path=SelectedItem.Tag, Converter={local:TagToVisibilityConverter}, ConverterParameter=myTag3}">
                    <!-- 这里放你的组内内容 -->
                </dxlc:LayoutGroup>
            </dxlc:LayoutControl>
        </dxdo:LayoutPanel>
    </dxdo:LayoutGroup>
</dxdo:DockLayoutManager>

配套转换器代码

需要写一个简单的转换器,用来根据Accordion选中项的Tag判断对应LayoutGroup是否显示:

using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;

namespace YourNamespace
{
    public class TagToVisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            // 对比选中项的Tag和当前Group的标识,匹配则显示,否则隐藏
            return string.Equals(value?.ToString(), parameter?.ToString(), StringComparison.Ordinal) 
                ? Visibility.Visible 
                : Visibility.Collapsed;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

然后在XAML的资源里注册这个转换器:

<Window.Resources>
    <local:TagToVisibilityConverter x:Key="TagToVisibilityConverter"/>
</Window.Resources>

方案二:仅用LayoutControl实现

如果你不想用DockLayoutManager,单纯用LayoutControl也能实现,代码如下:

<dxlc:LayoutControl Orientation="Horizontal">
    <!-- 左侧Accordion组,固定宽度 -->
    <dxlc:LayoutGroup Width="200" VerticalAlignment="Stretch">
        <dxa:AccordionControl x:Name="mainAccordion" SelectionMode="Single">
            <dxa:AccordionItem Header="标签1" Tag="myTag1"/>
            <dxa:AccordionItem Header="标签2" Tag="myTag2"/>
            <dxa:AccordionItem Header="标签3" Tag="myTag3"/>
        </dxa:AccordionControl>
    </dxlc:LayoutGroup>
    
    <!-- 右侧内容组,自动填充剩余空间 -->
    <dxlc:LayoutGroup VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
        <dxlc:LayoutGroup x:Name="myTag1" Header="LayoutGroup 1" 
                         Visibility="{Binding ElementName=mainAccordion, Path=SelectedItem.Tag, Converter={StaticResource TagToVisibilityConverter}, ConverterParameter=myTag1}">
            <!-- 组内内容 -->
        </dxlc:LayoutGroup>
        <dxlc:LayoutGroup x:Name="myTag2" Header="LayoutGroup 2" 
                         Visibility="{Binding ElementName=mainAccordion, Path=SelectedItem.Tag, Converter={StaticResource TagToVisibilityConverter}, ConverterParameter=myTag2}">
            <!-- 组内内容 -->
        </dxlc:LayoutGroup>
        <dxlc:LayoutGroup x:Name="myTag3" Header="LayoutGroup 3" 
                         Visibility="{Binding ElementName=mainAccordion, Path=SelectedItem.Tag, Converter={StaticResource TagToVisibilityConverter}, ConverterParameter=myTag3}">
            <!-- 组内内容 -->
        </dxlc:LayoutGroup>
    </dxlc:LayoutGroup>
</dxlc:LayoutControl>

额外优化:MVVM模式下的实现

如果你的项目用了MVVM,可以把Accordion的SelectedItem绑定到ViewModel的属性,然后在ViewModel里控制每个LayoutGroup的可见性,更符合MVVM规范:

ViewModel示例

public class MainViewModel : INotifyPropertyChanged
{
    private AccordionItem _selectedNavItem;
    public AccordionItem SelectedNavItem
    {
        get => _selectedNavItem;
        set
        {
            _selectedNavItem = value;
            OnPropertyChanged();
            UpdateLayoutGroupVisibility();
        }
    }

    private bool _isTag1Visible;
    public bool IsTag1Visible
    {
        get => _isTag1Visible;
        set { _isTag1Visible = value; OnPropertyChanged(); }
    }

    private bool _isTag2Visible;
    public bool IsTag2Visible
    {
        get => _isTag2Visible;
        set { _isTag2Visible = value; OnPropertyChanged(); }
    }

    private bool _isTag3Visible;
    public bool IsTag3Visible
    {
        get => _isTag3Visible;
        set { _isTag3Visible = value; OnPropertyChanged(); }
    }

    private void UpdateLayoutGroupVisibility()
    {
        IsTag1Visible = SelectedNavItem?.Tag.ToString() == "myTag1";
        IsTag2Visible = SelectedNavItem?.Tag.ToString() == "myTag2";
        IsTag3Visible = SelectedNavItem?.Tag.ToString() == "myTag3";
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

对应的XAML绑定

<dxlc:LayoutGroup x:Name="myTag1" Header="LayoutGroup 1" 
                 Visibility="{Binding IsTag1Visible, Converter={StaticResource BooleanToVisibilityConverter}}">

这样就不用自己写Tag转换器,直接用DevExpress自带的BooleanToVisibilityConverter就行啦。

内容的提问来源于stack exchange,提问作者Tom Mackie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:25:49