Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF expander validation error not shown when expanded

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>
like image 752
Nix Avatar asked Jun 11 '12 10:06

Nix


1 Answers

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

like image 147
akjoshi Avatar answered Sep 18 '22 04:09

akjoshi