views:

2689

answers:

2

We have a scenario where we want to display a list of items and indicate which is the "current" item (with a little arrow marker or a changed background colour).

ItemsControl is no good to us, because we need the context of "SelectedItem". However, we want to move the selection programattically and not allow the user to change it.

Is there a simple way to make a ListBox non-interactive? We can fudge it by deliberately swallowing mouse and keyboard events, but am I missing some fundamental property (like setting "IsEnabled" to false without affecting its visual style) that gives us what we want?

Or ... is there another WPF control that's the best of both worlds - an ItemsControl with a SelectedItem property?

+1  A: 

Is your ItemsControl/ListBox databound?

I'm just thinking you could make the Background Brush of each item bound to a property from the source data, or pass the property through a converter. Something like:

  <ItemsControl DataContext="{Binding Source={StaticResource Things}}" ItemsSource="{Binding}" Margin="0">
    <ItemsControl.Resources>
      <local:SelectedConverter x:Key="conv"/>
    </ItemsControl.Resources>
    <ItemsControl.ItemsPanel>
      <ItemsPanelTemplate>
        <local:Control Background="{Binding Path=IsSelected, Converter={StaticResource conv}}"/>
      </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
Mark Glorie
+8  A: 

One option is to set ListBoxItem.IsEnabled to false:

<ListBox x:Name="_listBox">
    <ListBox.ItemContainerStyle>
     <Style TargetType="ListBoxItem">
      <Setter Property="IsEnabled" Value="False"/>
     </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

This ensures that the items are not selectable, but they may not render how you like. To fix this, you can play around with triggers and/or templates. For example:

<ListBox x:Name="_listBox">
    <ListBox.ItemContainerStyle>
     <Style TargetType="ListBoxItem">
      <Setter Property="IsEnabled" Value="False"/>
      <Style.Triggers>
       <Trigger Property="IsEnabled" Value="False">
        <Setter Property="Foreground" Value="Red" />
       </Trigger>
      </Style.Triggers>
     </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

HTH, Kent

Kent Boogaart
Your ControlTemplate is doing a DataTemplate's job. All you need in addition to the Setter for IsEnabled is <Trigger Property="IsEnabled" Value="False"><Setter Property="Foreground" Value="{StaticResource fgbrush}" /></Trigger>
Joel B Fant
Good point Joel. Will change my example accordingly.
Kent Boogaart