0

I have created a number of controls that (slightly) extend the functionality of many UIElements to include an IsError and IsCorrect properties, which are used to signify error conditions to the user.

For example, the extended Checkbox.

public class EBC_CheckBox : CheckBox
{
    public static readonly DependencyProperty IsCorrectProperty = DependencyProperty.Register("IsCorrect", typeof(bool), typeof(EBC_CheckBox), new UIPropertyMetadata(false));
    public static readonly DependencyProperty IsErrorProperty = DependencyProperty.Register("IsError", typeof(bool), typeof(EBC_CheckBox), new UIPropertyMetadata(false));

    public EBC_CheckBox() : base()
    {
        IsError = false;
        IsCorrect = false;
    }

    public bool IsError
    {
        get { return (bool)GetValue(IsErrorProperty); }
        set { SetValue(IsErrorProperty, value); }
    }

    public bool IsCorrect
    {
        get { return (bool)GetValue(IsCorrectProperty); }
        set { SetValue(IsCorrectProperty, value); }
    }

This is styled in the XAML code as:

<Style TargetType="{x:Type local:EBC_CheckBox}">
    <Setter Property="Foreground" Value="{StaticResource SBase02}"/>
    <Setter Property="Background" Value="{StaticResource SBase0}"/>
    <Setter Property="FontSize" Value="14"/>
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="Margin" Value="0,2,8,2"/>
    <Setter Property="BorderBrush" Value="{StaticResource SYellow}"/>
    <Setter Property="BorderThickness" Value="2"/>
    <Style.Triggers>
        <Trigger Property="IsEnabled" Value="False">
            <Setter Property="Foreground" Value="{StaticResource SBase01}"/>
            <Setter Property="BorderThickness" Value="0"/>
        </Trigger>
        <Trigger Property="IsError" Value="True">
            <Setter Property="BorderBrush" Value="{StaticResource SRed}"/>
        </Trigger>
        <Trigger Property="IsCorrect" Value="True">
            <Setter Property="BorderBrush" Value="{StaticResource SGreen}"/>
        </Trigger>
    </Style.Triggers>
</Style>

My issue is that I would like to add some of the checkboxes to a ListBox and for the most part this works. However, the extended properties are ignored, it would appear that the ListBox is just presenting the items as normal UIElements, not as the extended versions.

<ListBox  ItemsSource="{Binding MyObjects}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <local:EBC_CheckBox Content="{Binding Path=Name}" IsChecked="{Binding Path=IsPresent}" IsError="{Binding Path=IsError}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

How can I get the objects to display inside the ListBox along with the extended properties (so red when IsError is set, etc.)?

Following on from Damir's response, if I use a datatrigger I can set the style of the overall ListBoxItem (i.e. setting the border sets a border around the entire item, not just changes the color of the checkbox).

<Style TargetType="{x:Type ListBoxItem}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding IsError}" Value="True">
            <Setter Property="BorderBrush" Value="Red"/>
        </DataTrigger>
    </Style.Triggers>
</Style>

Is it possible to do something like this and reuse the controls formatting, or do I need to create a custom list box with customised listboxitems?

<Style TargetType="{x:Type ListBoxItem}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding IsError}" Value="True">
            <Setter Property="local:EBC_CheckBox.IsError" Value="True"/>
        </DataTrigger>
    </Style.Triggers>
</Style>

Further Edit:

I have found that the following code works, which is using a fixed list of items:

<ListBox HorizontalAlignment="Left" Height="100" Margin="72,383,0,0" Grid.Row="1" VerticalAlignment="Top" Width="100">
    <local:EBC_CheckBox Content="Item1" IsCorrect="True"/>
    <local:EBC_CheckBox Content="Item2" IsChecked="True"/>
    <local:EBC_CheckBox Content="Item3" IsError="True"/>
    <local:EBC_CheckBox Content="Item4" />
</ListBox>

The list displays the items and their visual state is correctly handled according the EBC_CheckBox settings.

If I change to a list of bound items though the visual side of things is not correctly updated - the Content and IsChecked fields are correctly handled (expected as these are in the base Checkbox, but the IsError field is ignored)

<ListBox Grid.Column="3" Grid.Row="8" HorizontalAlignment="Left" VerticalAlignment="Top" BorderThickness="0"
         ItemsSource="{Binding Things}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <local:EBC_CheckBox Content="{Binding Path=ThingName}" IsChecked="{Binding Path=IsPresent}" IsError="{Binding Path=IsError}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

What am I missing???

2 Answers 2

1

Sorted out the issue, it all came down to the setting of the dependency properties in the constructor. These settings should not be there, setting these in the constructor overwrites and bound values in the application.

See also this question.

Sign up to request clarification or add additional context in comments.

Comments

0

You must use a DataTrigger instead simple Trigger for correct binding. Try this:

            <DataTrigger Binding="{Binding IsError}" Value="True">
                <Setter Property="BorderBrush" Value="Red" />
                <Setter Property="FontSize" Value="20"/>
            </DataTrigger>

1 Comment

This lets me set the formatting of the ListBoxItem but only as a normal UIElement, I would like to know if I can somehow get the ListBox to display the customised checkboxes as themselves, not as normal checkboxes (I'll expand above).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.