Phillip Benages
Phillip Benages

Reputation: 671

Disable ComboBox Without Changing Appearance

Is there a way to disable changing the value of a ComboBox in WPF without giving it the visual properties of a disabled ComboBox? For example, I know that for a text field you can set the IsReadOnly property to true. Doing this for a ComboBox however, does not prevent the user from selecting a different value.

Upvotes: 4

Views: 5856

Answers (7)

CZahrobsky
CZahrobsky

Reputation: 830

...prevent the user from selecting a different value.

On top of styling you can disable keyboard input by overriding some ComboBox methods:

using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Input;

public class LockableComboBox : ComboBox
{

    protected override void OnSelectionChanged(SelectionChangedEventArgs e)
    {
        if (this.IsReadOnly)
        {
            e.Handled = true;
        }
        else
        {
            base.OnSelectionChanged(e);
        }
    }

    protected override void OnPreviewKeyDown(KeyEventArgs e)
    {
        if (this.IsReadOnly)
        {
            if ((e.Key == Key.C || e.Key == Key.Insert)
                && (Keyboard.Modifiers & ModifierKeys.Control) 
                == ModifierKeys.Control)
            {
                // Allow copy
                Clipboard.SetDataObject(SelectedValue, true);
            }
            e.Handled = true;
        }
        else
        {
            base.OnPreviewKeyDown(e);
        }
    }

    protected override void OnPreviewTextInput(TextCompositionEventArgs e)
    {
        if (this.IsReadOnly) 
        {
            e.Handled = true;
        }
        else
        {
            base.OnPreviewTextInput(e);
        }
    }

    protected override void OnKeyUp(KeyEventArgs e)
    {
        if (this.IsReadOnly)
        {
            e.Handled = true;
        }
        else
        {
            base.OnKeyUp(e);
        }
    }
}

Upvotes: 0

Lee Louviere
Lee Louviere

Reputation: 5262

Why then, use a comboBox.

My choice would be a label within a border that takes the place of the control, indicating that this is a display-only screen.

If it must look like a combobox, it would be better to use an object themed like a button but not clickable. You could even draw a gray dropdown arrow so it better looks like a comboBox.

It just seems overkill to actually have a combobox on the screen that people can't interact with, when a label would do fine.

Upvotes: 0

Thomas Visic
Thomas Visic

Reputation: 106

Mr. Benages, I think setting IsHitTestVisible and Focusable to false on the ComboBox might do the trick. Hope this helps.

Upvotes: 9

Crispy
Crispy

Reputation: 5637

You can set the Foreground and Background colors and that seems to override the disabled colors. The drop down button shows as disabled which is good.

EDIT My code I tested with in IE 6/Kaxaml.

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <StackPanel>
  <ComboBox  Foreground="black" Background="white" IsEditable="True" Text="Hello" IsEnabled="false">
  <ComboBoxItem>Test1</ComboBoxItem>
  <ComboBoxItem>Test2</ComboBoxItem>
  <ComboBoxItem>Test3</ComboBoxItem>
  </ComboBox>
  </StackPanel>
</Page>

Upvotes: 0

PaulB
PaulB

Reputation: 24372

While I agree that a disabled control should look disabled you could just set the ComboBox ControlTemplate to the standard one (or one your using) removing any of the standard functionality

eg This will give you a decent looking readonly combobox

  <ComboBox>
    <ComboBox.Template>
        <ControlTemplate TargetType="{x:Type ComboBox}">
          <Grid>
            <Microsoft_Windows_Themes:ListBoxChrome x:Name="Border" Height="23" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" RenderMouseOver="{TemplateBinding IsMouseOver}"/>
            <TextBlock FontSize="{TemplateBinding FontSize}" VerticalAlignment="Center" Text="Selected Item" Margin="5,0,0,0"></TextBlock>
          </Grid>
      </ControlTemplate>
    </ComboBox.Template>
  </ComboBox>

you'll need to include the following namespace

xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"

Upvotes: 4

Audioillity
Audioillity

Reputation: 313

Im not sure if its the same in .net however back in the VB6 days i use to get a picture box, frame or other container (sorry off the top of my head i can't remember which). I would put the combobox within that. To the users it looks the same. When you disable the container this would lock out the combo box as well, leaving it looking normal.

Upvotes: 1

steamer25
steamer25

Reputation: 9538

Are you sure this is a good idea from a usability/conventions standpoint? If your goal is readability, perhaps you can change the disabled color to bump up the contrast a bit.

http://social.msdn.microsoft.com/forums/en-US/wpf/thread/45dd7614-326b-4a51-b809-d25a3ff1ade8/

Anyway, I suspect you could write an onChange event handler to reset the value to the previous entry.

Upvotes: 0

Related Questions