Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF ListBox ErrorTemplate

In my WPF application I've a ListBox binding to a collection of view models. Those view models support validation by implement INotifyDataErrorInfo. I’m trying to display an error template for items with validation errors in my ListBox.

I’m able to get the ListBox to display the default error template by setting NotifyOnValidationError=True on the ItemSource binding of the ListBox.
Which looks like this: enter image description here

Code of my ListBox:

<ListBox x:Name="ListBoxEvents" ItemsSource="{Binding Events, UpdateSourceTrigger=PropertyChanged, NotifyOnValidationError=True}" 
                 IsSynchronizedWithCurrentItem="True" ItemTemplate="{DynamicResource EventListTemplate}"></ListBox>

My ListBox style:

<ControlTemplate x:Key="ListBoxValidationError">
    <DockPanel LastChildFill="True">
        <Border Background="Red" Margin="5">
            <AdornedElementPlaceholder />
        </Border>
    </DockPanel>
</ControlTemplate>

<Style TargetType="{x:Type ListBox}">
    <Setter Property="BorderBrush" Value="{StaticResource WindowTitleBrush}" />
    <Setter Property="BorderThickness" Value="1" />
    <Setter Property="MinWidth" Value="200" />
    <Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
    <Setter Property="ScrollViewer.CanContentScroll" Value="False"></Setter>
    <Setter Property="Validation.ErrorTemplate" Value="{StaticResource ListBoxValidationError}"></Setter>
</Style>

The ListBox item template:

<DataTemplate x:Key="EventListTemplate" DataType="{x:Type event:EventViewModel}">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

       <TextBlock Text="{Binding Title, Converter={StaticResource EmptyStringConverter}, ConverterParameter='-'}" FontWeight="Bold" FontSize="14" />
        <TextBlock Text="{Binding Date, StringFormat={}{0:dd.MM.yyyy}}" Grid.Row="1" Grid.Column="0" FontStyle="Italic" />
        <Button Grid.Column="1" Grid.RowSpan="2" Grid.Row="0" Style="{DynamicResource ItemDeleteButton}" />
    </Grid>
</DataTemplate>

How can I display a custom error template for my ListBoxItems? (My goal is to make the background of the items red)

like image 609
musium Avatar asked Nov 08 '22 17:11

musium


1 Answers

You can specify Valdiation.ErrorTemplate on ListBoxItem as well in ItemContainerStyle:

<ListBox>
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="Validation.ErrorTemplate">
                <Setter.Value>
                    <ControlTemplate>
                        <Border Background="Red" Opacity="0.2">
                            <AdornedElementPlaceholder/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

Most likely you want to show it on ListBoxItem when any property in item throws an error. Say Name property in ListBoxItem data is invalid which is bind to TextBox. Set ValidatesOnDataErrors to true on textbox and set Validation.ValidationAdornerSite to parent ListBoxItem.

For sample:

<ListBox>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBox Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"
                     Validation.ValidationAdornerSite="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="Validation.ErrorTemplate">
                <Setter.Value>
                    <ControlTemplate>
                        <Border Background="Red" Opacity="0.2">
                           <AdornedElementPlaceholder/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>
like image 108
Rohit Vats Avatar answered Nov 15 '22 07:11

Rohit Vats