I have some templates for an expander object and created a user control for it. Everything is fine as long as I add the same user control again into the content. Then, unfortunately, the height of the parent expander (UC) will not decrease when the child expander (UC) is downscaled:
How can I achieve this?
App.xaml:
<Application x:Class="SampleExpander.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:local ="clr-namespace:SampleExpander"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ControlTemplate x:Key="AnimatedExpanderButtonTemp2" TargetType="{x:Type ToggleButton}">
<Border x:Name="ExpanderButtonBorder" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Rectangle Fill="Transparent" Grid.ColumnSpan="2"/>
<Ellipse Name="Circle" Grid.Column="0" Stroke="Transparent" Width="40" Height="40" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Image x:Name="Arrow" Grid.Column="0" Source="Resources/ArrowDown.png" Width="30" Height="30" RenderTransformOrigin="0.5,0.5" HorizontalAlignment="Center" VerticalAlignment="Center">
<Image.RenderTransform>
<RotateTransform Angle="270"/>
</Image.RenderTransform>
</Image>
<ContentPresenter x:Name="HeaderContent" Grid.Column="1" Margin="4,0,0,0" ContentSource="Content" HorizontalAlignment="Stretch"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="Arrow" Storyboard.TargetProperty="(Image.RenderTransform).(RotateTransform.Angle)" To="360" Duration="0:0:0.2"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="Arrow" Storyboard.TargetProperty="(Image.RenderTransform).(RotateTransform.Angle)" To="270" Duration="0:0:0.2"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<local:MultiplyConverter x:Key="multiplyConverter" />
<ControlTemplate x:Key="RevealExpanderTemp2" TargetType="{x:Type Expander}">
<DockPanel>
<ToggleButton x:Name="ExpanderButton" DockPanel.Dock="Top" Template="{StaticResource AnimatedExpanderButtonTemp2}" Content="{TemplateBinding Header}" IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" OverridesDefaultStyle="True" Padding="1.5,0"/>
<ScrollViewer x:Name="ExpanderContentScrollView" DockPanel.Dock="Bottom" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Bottom">
<ScrollViewer.Tag>
<sys:Double>0.0</sys:Double>
</ScrollViewer.Tag>
<ScrollViewer.Height>
<MultiBinding Converter="{StaticResource multiplyConverter}">
<Binding Path="ActualHeight" ElementName="ExpanderContent"/>
<Binding Path="Tag" RelativeSource="{RelativeSource Self}" />
</MultiBinding>
</ScrollViewer.Height>
<ContentPresenter x:Name="ExpanderContent" ContentSource="Content"/>
</ScrollViewer>
</DockPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="ExpanderContentScrollView" Storyboard.TargetProperty="Tag" To="1" Duration="0:0:0.2"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="ExpanderContentScrollView" Storyboard.TargetProperty="Tag" To="0" Duration="0:0:0.2"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Application.Resources>
MultiplyConverter:
public class MultiplyConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
double result = 1.0;
for (int i = 0; i < values.Length; i++)
{
if (values[i] is double)
result *= (double)values[i];
}
return result;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new Exception("Not implemented");
}
}
UC3.xaml:
<UserControl x:Class="SampleExpander.UC3"
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"
xmlns:local="clr-namespace:SampleExpander"
mc:Ignorable="d" >
<Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Top">
<Expander Margin="10" Template="{StaticResource RevealExpanderTemp2}" OverridesDefaultStyle="True" x:Name="expTest" >
<Expander.Header>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="txtDescription" Grid.Column="0" FontSize="18" Foreground="Black" VerticalAlignment="Center"/>
<TextBlock x:Name="txtContent" Grid.Column="1" FontSize="18" Margin="10,0,10,0" Foreground="Black" VerticalAlignment="Center"/>
<Button x:Name="btnRemove" Grid.Column="2" Width="40" Height="40" Background="#F8CECC" Content="X" FontWeight="Normal" FontSize="18" BorderBrush="#B95753" Visibility="Collapsed">
<Button.Resources>
<Style TargetType="Border">
<Setter Property="CornerRadius" Value="3"/>
</Style>
</Button.Resources>
</Button>
</Grid>
</Expander.Header>
</Expander>
</Border>
UC3.xaml.cs:
public partial class UC3 : UserControl
{
public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register("Description", typeof(string), typeof(UC3), new PropertyMetadata(PropChanged));
public static readonly DependencyProperty ContentCapturesProperty = DependencyProperty.Register("ContentCaptures", typeof(string), typeof(UC3), new PropertyMetadata(PropChanged));
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof(object), typeof(UC3), new PropertyMetadata(PropChanged));
public event EventHandler Remove;
public string Description
{
get { return (string)GetValue(DescriptionProperty); }
set { SetValue(DescriptionProperty, value); }
}
public string ContentCaptures
{
get { return (string)GetValue(ContentCapturesProperty); }
set { SetValue(ContentCapturesProperty, value); }
}
public object Content
{
get { return (object)GetValue(ContentProperty); }
set { SetValue(ContentProperty, value); }
}
public UC3()
{
InitializeComponent();
btnRemove.Click += BtnRemove_Click;
}
private void BtnRemove_Click(object sender, RoutedEventArgs e)
{
Remove?.Invoke(this, null);
}
public static void PropChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
switch (e.Property.Name)
{
case "Description":
((UC3)sender).txtDescription.Text = e.NewValue.ToString();
break;
case "ContentCaptures":
((UC3)sender).txtContent.Text = e.NewValue.ToString();
break;
case "Content":
((UC3)sender).expTest.Content = e.NewValue;
break;
default:
break;
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show(Description);
}
}
MainWindow.xaml:
<StackPanel Orientation="Vertical">
<local:UC3 Description="This is a description" ContentCaptures="(Test)" Margin="10" x:Name="ucTest">
<local:UC3 Description="4 Packungen" Margin="10">
<StackPanel Orientation="Vertical" Margin="10">
<Label Content="1. QCBDRa1xyzgdfhnfgdfsfewrt44523412edafsf" />
<Label Content="2. QCBDRa1xyzgdfhnfgdfsfewrt44523ddx2edasf" />
<Label Content="3. QCBDRa1xyzgdfhnfgdfsfewrt4453423112sasf" />
<Label Content="4. QCBDRa1xyzgdfhrrrasdewrt4998854511fddsd" />
</StackPanel>
</local:UC3>
</local:UC3>
</StackPanel>
THANK YOU FOR YOUR HELP!!
UPDATE: I tried to subscribe to all the underlying Expander.Collapsed events to decrease the height manually when one sub Expander gets collapsed. It worked once, but after that the height will no longer change when expanding again.
private void SubExpander_Collapsed(object sender, RoutedEventArgs e)
{
var collpasedTemplate = ((Expander)sender).Template;
var collapsedScrollViewer = (ScrollViewer)collpasedTemplate.FindName("ExpanderContentScrollView", (Expander)sender);
double oldHeight = collapsedScrollViewer.ActualHeight;
var template = expTest.Template;
var scrollViewer = (ScrollViewer)template.FindName("ExpanderContentScrollView", expTest);
scrollViewer.Height -= oldHeight;
}

First - you don't need all the stuff with
ScrollViewer.Tag, remove it. You can accessExpandervia binding. You also don't need to subscribe the expander, let the things be done by the framework.The issue, that you have, I think, that through explicit setting the
ScrollViewer.Heightto the real value, the automatic recalculation, which being done by the framework, stopped to work.So all you need instead of setting the
ScrollViewer.Heightto theActualHeightof expander content just set it todouble.NaN. ThenScrollViewer.Heightwill look like:and converter will be: