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
相关产品推荐
相关产品推荐

