Bueno aquí dejo publicado la solución de un problema que recientemente tuve haciendo que funcionaran juntos un Expander y un splitter, bueno la meta final era tener 2 expanders separados por 1 splitter y que cada expander contuviera algún tipo de grid o incluso una vista, con este aproach ya se puede jugar con lo que uno quiera poner en cada region.
Yo anduve buscando algo similar y no pude encontrar mucho al respecto así que aquí dejo mi solución y espero que a alguien pueda servirle..
Aquí tenemos el XAML con el código que contiene al expander y al splitter o más bien dos expander conteniendo un grid cada uno separados por un splitter..
View.xaml
<window x:Class="ExpanderAndSplitter.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525" x:Name="MainWdw"> <grid x:Name="MainContainer" Loaded="MainContainer_Loaded" Margin="5,5,5,5" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Background="Transparent"> </grid><grid .ColumnDefinitions> <columndefinition Width="Auto" /> <columndefinition Width="Auto" /> <columndefinition Width="Auto" /> <columndefinition Width="*" /> <columndefinition Width="Auto" /> </grid> <grid .RowDefinitions> <rowdefinition Height="Auto"/> <rowdefinition Height="*"/> </grid> <label x:Name="DummyLabel" Content="Dummy Label" /> <combobox x:Name="DummyComboBox" Grid.Column="1" MinWidth="100" Margin="0,0,5,0"/> <button Grid.Column="2" Width="100" Content="Dummy Button" /> <label x:Name="Label" Content="Dummy Label 2" Grid.Column="4" HorizontalAlignment="Right" /> <grid Grid.Row="1" Grid.ColumnSpan="5" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Background="Transparent"> </grid><grid .ColumnDefinitions> <columndefinition /> </grid> <grid .RowDefinitions> <rowdefinition x:Name="MasterRow" Height="{Binding MasterRowHeight, Mode=TwoWay}" /> <rowdefinition x:Name="SplitterRow" Height="{Binding SplitterRowHeight, Mode=TwoWay}" /> <rowdefinition x:Name="DetailRow" Height="{Binding DetailRowHeight, Mode=TwoWay}" /> </grid> <expander x:Name="MasterExpander" IsExpanded="True" BorderBrush="Gray" Margin="0,5,0,0" BorderThickness="1" IsEnabled="True" ExpandDirection="Down" Background="Transparent" Expanded="MasterExpander_Expanded" Collapsed="MasterExpander_Collapsed" > </expander><expander .Header> <textblock FontWeight="Bold" Text="Master Region" /> </expander> <grid Background="Transparent"> </grid><grid .ColumnDefinitions> <columndefinition Width="*" /> </grid> <grid .RowDefinitions> <rowdefinition Height="*"/> </grid> <datagrid x:Name="MasterGrid" Loaded="MasterGrid_Loaded" AutoGenerateColumns="True" CanUserDeleteRows="False" ColumnWidth="*" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/> <gridsplitter Grid.Row="1" Background="Gray" BorderThickness="1,1,1,1" Width="Auto" HorizontalAlignment="Stretch" Height="6" VerticalContentAlignment="Top" Padding="0,0,0,0" Margin="5,0,5,0" VerticalAlignment="Center"/> <expander x:Name="DetailExpander" Grid.Row="2" Margin="0,5,0,0" BorderBrush="Gray" BorderThickness="1" IsEnabled="True" ExpandDirection="Down" Background="Transparent" Expanded="DetailExpander_Expanded" Collapsed="DetailExpander_Collapsed" > </expander><expander .Header> <textblock FontWeight="Bold" Text="Detail Region" /> </expander> <grid Background="Transparent"> </grid><grid .ColumnDefinitions> <columndefinition Width="*" /> </grid> <grid .RowDefinitions> <rowdefinition Height="*"/> </grid> <datagrid x:Name="DetailGrid" Loaded="DetailGrid_Loaded" AutoGenerateColumns="True" CanUserDeleteRows="False" ColumnWidth="*" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/> </window>
Y su respectivo code behind que se encarga de hacer las operaciones correspondientes de tamaño para que estos controles funcionen armoniosamente uno con el otro..
View.xaml.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Collections.ObjectModel; namespace ExpanderAndSplitter { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { #region Fields private static double _oldMasterHeight = 1; private static double _oldDetailHeight = 1; #endregion // Fields #region Properties public GridLength MasterRowHeight { get { return (GridLength)GetValue(MasterRowHeightProperty); } set { SetValue(MasterRowHeightProperty, value); } } // Using a DependencyProperty as the backing store for MasterRowHeight. This enables animation, styling, binding, etc... public static readonly DependencyProperty MasterRowHeightProperty = DependencyProperty.Register("MasterRowHeight", typeof(GridLength), typeof(MainWindow), new UIPropertyMetadata(new GridLength(1, GridUnitType.Star))); public GridLength SplitterRowHeight { get { return (GridLength)GetValue(SplitterRowHeightProperty); } set { SetValue(SplitterRowHeightProperty, value); } } // Using a DependencyProperty as the backing store for SplitterRowHeight. This enables animation, styling, binding, etc... public static readonly DependencyProperty SplitterRowHeightProperty = DependencyProperty.Register("SplitterRowHeight", typeof(GridLength), typeof(MainWindow), new UIPropertyMetadata(new GridLength(0))); public GridLength DetailRowHeight { get { return (GridLength)GetValue(DetailRowHeightProperty); } set { SetValue(DetailRowHeightProperty, value); } } // Using a DependencyProperty as the backing store for DetailRowHeight. This enables animation, styling, binding, etc... public static readonly DependencyProperty DetailRowHeightProperty = DependencyProperty.Register("DetailRowHeight", typeof(GridLength), typeof(MainWindow), new UIPropertyMetadata(new GridLength(1, GridUnitType.Auto))); public ObservableCollection<DummyItem> MasterItems { get; set; } public ObservableCollection<DummyItem> DetailItems { get; set; } #endregion // Properties #region Constructors public MainWindow() { InitializeComponent(); MasterItems = new ObservableCollection<DummyItem>(); DetailItems = new ObservableCollection<DummyItem>(); for (int i=0; i<1000; i++) { MasterItems.Add(new DummyItem("Master Dummy " + i.ToString(), i.ToString())); DetailItems.Add(new DummyItem("Detail Dummy " + i.ToString(), i.ToString())); } } #endregion // Constructors #region Events private void MasterExpander_Expanded(object sender, RoutedEventArgs e) { DoHandleExpandCollapse(); } private void MasterExpander_Collapsed(object sender, RoutedEventArgs e) { if (DetailExpander.IsExpanded) { _oldMasterHeight = MasterRowHeight.Value; _oldDetailHeight = DetailRowHeight.Value; } DoHandleExpandCollapse(); } private void DetailExpander_Expanded(object sender, RoutedEventArgs e) { DoHandleExpandCollapse(); } private void DetailExpander_Collapsed(object sender, RoutedEventArgs e) { if (MasterExpander.IsExpanded) { _oldMasterHeight = MasterRowHeight.Value; _oldDetailHeight = DetailRowHeight.Value; } DoHandleExpandCollapse(); } private void MasterGrid_Loaded(object sender, RoutedEventArgs e) { if (MasterGrid.ItemsSource == null) MasterGrid.ItemsSource = MasterItems; } private void DetailGrid_Loaded(object sender, RoutedEventArgs e) { if (DetailGrid.ItemsSource == null) DetailGrid.ItemsSource = DetailItems; } private void MainContainer_Loaded(object sender, RoutedEventArgs e) { MainContainer.DataContext = this; } #endregion // Events #region Helpers private void DoHandleExpandCollapse() { if (MasterExpander == null || DetailExpander == null) return; SplitterRowHeight = new GridLength(0); if (MasterExpander.IsExpanded && DetailExpander.IsExpanded) { MasterRowHeight = new GridLength(_oldMasterHeight, GridUnitType.Star); DetailRowHeight = new GridLength(_oldDetailHeight, GridUnitType.Star); SplitterRowHeight = new GridLength(20); return; } if (MasterExpander.IsExpanded) MasterRowHeight = new GridLength(1, GridUnitType.Star); else MasterRowHeight = new GridLength(1, GridUnitType.Auto); if (DetailExpander.IsExpanded) DetailRowHeight = new GridLength(1, GridUnitType.Star); else DetailRowHeight = new GridLength(1, GridUnitType.Auto); } #endregion // Helpers } public class DummyItem { public DummyItem(string name, string id) { this.Name = name; this.ID = id; } public string Name { get; set; } public string ID { get; set; } } }
Al final así es como luce la solución:
La solución ejemplo esta hecha con Visual Studio 2010 y el código fuente lo puedes bajar del siguiente link ExpanderAndSplitter.
¡Enjoy! 🙂
Yohan Rodriguez