2

I have a ComboBox binding to an ObservableCollection<ElementType> collection. I want to have unselectable separators where both Name and Type properties are set to null. When name is set to a string and Type is null, I want it to be an unselectable header/title. Otherwise, I want the elements to be selectable elements, but with a slight margin.

This is where I am so far:

enter image description here

My two problems are:

  • The selected item is shown as ElementType object with full name space, rather than the Name string.
  • Highlighting of the enabled elements are no longer shown on MouseOver.

XAML:

<ComboBox Grid.Column="1" Grid.Row="2" Style="{StaticResource ElementTypeComboBoxStyle}"
            ItemsSource="{Binding Path=Element.ElementTypeList}"
            SelectedItem="{Binding Path=Element.SelectedElementType}">
    <ComboBox.Resources>
        <converters:NullToBooleanConverter x:Key="NullToBooleanConverter" />
    </ComboBox.Resources>
    <ComboBox.ItemContainerStyle>
        <Style TargetType="{x:Type ComboBoxItem}">
            <Style.Triggers>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding Path=Name, Converter={StaticResource NullToBooleanConverter}}" Value="True" />
                        <Condition Binding="{Binding Path=Type, Converter={StaticResource NullToBooleanConverter}}" Value="True" />
                    </MultiDataTrigger.Conditions>
                    <Setter Property="IsEnabled" Value="False" />
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type ComboBoxItem}">
                                <Separator HorizontalAlignment="Stretch" />
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding Path=Name, Converter={StaticResource NullToBooleanConverter}}" Value="False" />
                        <Condition Binding="{Binding Path=Type, Converter={StaticResource NullToBooleanConverter}}" Value="True" />
                    </MultiDataTrigger.Conditions>
                    <Setter Property="IsEnabled" Value="False" />
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type ComboBoxItem}">
                                <TextBlock Text="{Binding Path=Name}" />
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding Path=Name, Converter={StaticResource NullToBooleanConverter}}" Value="False" />
                        <Condition Binding="{Binding Path=Type, Converter={StaticResource NullToBooleanConverter}}" Value="False" />
                    </MultiDataTrigger.Conditions>
                    <Setter Property="IsEnabled" Value="True" />
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type ComboBoxItem}">
                                <TextBlock Text="{Binding Path=Name}" Margin="10,0,0,0" />
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </MultiDataTrigger>
            </Style.Triggers>
        </Style>
    </ComboBox.ItemContainerStyle>
</ComboBox>

C#:

public class ElementType {
    public ElementType(string name, Type type) {
        Name = name;
        Type = type;
    }
    public string Name { get; private set; }
    public Type Type { get; private set; }
}

private static ObservableCollection<ElementType> _elementTypeList = new ObservableCollection<ElementType> {
    // Controls
    new ElementType("Controls:", null),
    new ElementType("Analog Output Slider", typeof(AnalogOutputSliderControl)),
    new ElementType("Digital Output Button", typeof(DigitalOutputButtonControl)),

    new ElementType(null, null),  // Separator

    // Indicators
    new ElementType("Indicators:", null),
    new ElementType("Numeric Value", typeof(NumericValueIndicator)),
    new ElementType("ROV Illustration", typeof(RovIllustration)),
    new ElementType("Trend Graph", typeof(TrendGraphIndicator)),

    new ElementType(null, null),  // Separator

    // Generic element
    new ElementType("None", typeof(Element))
};
[XmlIgnore]
public static ObservableCollection<ElementType> ElementTypeList { get { return _elementTypeList; } }
Oystein
  • 1,232
  • 11
  • 26
  • 1
    The first problem you can solve by using different templates for text and for dropdown, see [this question](https://stackoverflow.com/q/4672867/1997232). As for the second one - it's not clear what you want instead. Also, how does this solution works with arrow keys selection (without dropdown)? – Sinatr Nov 06 '17 at 10:32
  • As @Sinatr pointed out this is perfect scenario for Template Selector. – XAMlMAX Nov 06 '17 at 10:38
  • 1
    The easiest solution to keep highlighting is do not disable anything, but simply prevent e.g. separator to be set as `SelectedItem` during validation. That would also work with arrow keys. – Sinatr Nov 06 '17 at 10:39
  • @Sinatr I don't want to go for a Template Selector. I like the idea in your last post though. But I couldn't get it to work, as it both highlights the separators and headers on mouseover, and I haven't been able to prevent selection of separators or headers. Can you please elaborate a little in an answer? – Oystein Nov 06 '17 at 11:47

1 Answers1

0

I opted not to go for a Template Selector, since I thought it to be a bit heavy for my needs. I found a way around the problem in XAML, giving me the following result. It also works with arrow keys, since the separator and headers are disabled. Only "problem" is the gray color of the headers, but I'm leaving it as it is for now.

enter image description here

XAML:

<ComboBox Grid.Column="1" Grid.Row="2" Style="{StaticResource ElementTypeComboBoxStyle}"
            ItemsSource="{Binding Path=Element.ElementTypeList}"
            SelectedItem="{Binding Path=Element.SelectedElementType}">
    <ComboBox.Resources>
        <converters:NullToBooleanConverter x:Key="NullToBooleanConverter" />
    </ComboBox.Resources>
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Path=Name}" />
        </DataTemplate>
    </ComboBox.ItemTemplate>
    <ComboBox.ItemContainerStyle>
        <Style TargetType="{x:Type ComboBoxItem}">
            <Setter Property="IsEnabled" Value="False" />
            <Style.Triggers>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding Path=Name, Converter={StaticResource NullToBooleanConverter}}" Value="True" />
                        <Condition Binding="{Binding Path=Type, Converter={StaticResource NullToBooleanConverter}}" Value="True" />
                    </MultiDataTrigger.Conditions>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type ComboBoxItem}">
                                <Separator HorizontalAlignment="Stretch" />
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </MultiDataTrigger>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding Path=Name, Converter={StaticResource NullToBooleanConverter}}" Value="False" />
                        <Condition Binding="{Binding Path=Type, Converter={StaticResource NullToBooleanConverter}}" Value="False" />
                    </MultiDataTrigger.Conditions>
                    <Setter Property="IsEnabled" Value="True" />
                    <Setter Property="Padding" Value="10,0,0,0" />
                </MultiDataTrigger>                            
            </Style.Triggers>
        </Style>
    </ComboBox.ItemContainerStyle>
</ComboBox>
Oystein
  • 1,232
  • 11
  • 26