Using MVVM. I have a DataTemplate
which I am using to display an expander with some controls in per object.
<DataTemplate>
<Expander ExpandDirection="Down" IsExpanded="False">
<Expander.Header>
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="Platform Group {0} {1}">
<Binding Path="PlatformGroupCode"/>
<Binding Path="PlatformGroupName"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</Expander.Header>
<vw:PlatformGroup HorizontalAlignment="Left"/>
</Expander>
</DataTemplate>
Inside that view is 2 textboxes bound to those 2 properties. I'm using IDataErrorInfo
in my VM to do validation and I've a style in my main application resources to display error messages as tooltips:
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self},Path=(Validation.Errors).CurrentItem.ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
When a new group is added the 2 properties have default values, which is invalid so I want the textboxes to be red to prompt the user to enter data. This works if the Expander's IsExpanded is set to true. But if it is false I have to expand AND change the value in one of the textboxes in order to get the red border and tooltip to show.
I don't want to set the expander to be expanded because there will eventually be quite a few controls. How can I get the red border to show as soon as the expander is expanded? Even better, is there a way to make the newly added expander expand (when user adds a new group I'm adding a PlatformGroupviewModel to an observablecollection
of PlatformGroupviewModels)?
EDIT more detail: the top level view:
<StackPanel Orientation="Vertical">
<ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="630">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*" />
<ColumnDefinition Width="5*" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical" Grid.ColumnSpan="2" Grid.Row="1" HorizontalAlignment="Stretch">
<Expander ExpandDirection="Down" IsExpanded="True" Header="Header" HorizontalAlignment="Stretch" Name="expHeader" VerticalAlignment="Top">
<vw:Header DataContext="{Binding HeaderVM}"/>
</Expander>
<Expander ExpandDirection="Down" IsExpanded="True" Header="Platform Groups" HorizontalAlignment="Stretch" Name="expPlatformGroups" VerticalAlignment="Top">
<AdornerDecorator>
<vw:PlatformGroups DataContext="{Binding PlatformGroupsVM}"/>
</AdornerDecorator>
</Expander>
</StackPanel>
</Grid>
</ScrollViewer>
</StackPanel>
the PlatformGroups view:
<StackPanel Orientation="Vertical" HorizontalAlignment="Stretch" Margin="10,10,10,10">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch" Margin="0,10">
<Label Content="Number of platform groups" VerticalAlignment="Center"/>
<vw:IntegerInput MinValue="0" MaxValue="50" MaxLength="2" Text="{Binding Path=NumPlatformGroups, Mode=TwoWay,ValidatesOnDataErrors=True}" HorizontalAlignment="Left" VerticalAlignment="Center"/>
</StackPanel>
<ItemsControl IsTabStop="False" ItemsSource="{Binding PlatformGroups}" Margin="20,10" VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Expander ExpandDirection="Down" IsExpanded="False">
<Expander.Header>
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="Platform Group {0} {1}">
<Binding Path="PlatformGroupCode"/>
<Binding Path="PlatformGroupName"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</Expander.Header>
<AdornerDecorator>
<vw:PlatformGroup HorizontalAlignment="Left"/>
</AdornerDecorator>
</Expander>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.Template>
<ControlTemplate>
<Border BorderThickness="{TemplateBinding Border.BorderThickness}" Padding="{TemplateBinding Control.Padding}"
BorderBrush="{TemplateBinding Border.BorderBrush}" Background="{TemplateBinding Panel.Background}" SnapsToDevicePixels="True">
<ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="400" CanContentScroll="True" Padding="{TemplateBinding Control.Padding}" Focusable="False">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
</ControlTemplate>
</ItemsControl.Template>
</ItemsControl>
</StackPanel>
As per this post, wrapping your Expander
content inside an AdornerDecorator
should solve this problem -
<DataTemplate>
<Expander ExpandDirection="Down" IsExpanded="False">
<Expander.Header>
...
</Expander.Header>
<AdornerDecorator>
<vw:PlatformGroup HorizontalAlignment="Left"/>
</AdornerDecorator>
</Expander>
</DataTemplate>
Another SO thread which confirms this - Issue with WPF validation(IDataErrorInfo) and tab focusing
Some other WorkArounds are also mentioned on this connect bug -
TabControl doesn't display Validation error information correctly when switching tabs back and forth
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With