Search code examples
c#wpfcombobox

Watermark Behavior for ComboBox


I currently have a combobox bound to a dictionary. What I'm trying to do is have a default item in the combobox, such as "Please select an item...", which disappears when the user actually clicks on the combobox to select an item.

I've seen similar questions on this site, but can't seem to get any of the solutions to work properly for me. The only luck I've had is by putting this in my xaml combobox code:

<IsEditable="True" IsReadOnly="True" Text="Please select an item..."/>

But this of course changes the look of the combobox and I don't want it look editable.

My code behind:

private Dictionary<string, string> imageTypes = new Dictionary<string, string>();

public MainWindow()
{
    InitializeComponent();
    AddImage_Types();
}

public void AddImage_Types()
{
    imageTypes.Add("*.png", Png);
    imageTypes.Add("*.jpg *.jpeg *jfif", Jpg);
}

public Dictionary<string, string> ImageTypes
{
    get
    {
        return imageTypes;
    }
}

And here's my xaml for the combobox:

<ComboBox Name="imageCB"
          ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}, Path=ImageTypes}"
          SelectedValuePath="Value"
          DisplayMemberPath="Key" >
</ComboBox>

I've tried using triggers and styles as well like this answer: https://stackoverflow.com/a/16782339/2480598

I'm sure it's something simple, but I can't seem to get it.

Note: By default item, I mean that when the window is loaded, some text is already displayed in the combo box like "Please select an item...". This will go away when the user clicks the combo box to select an item from the dropdown.


Solution

  • The way you want to do this isn't really how WPF works. The best way to do this would be to use data validation / bindings, so user can't move on until something is selected; or a validation error is thrown (red lines around the combobox) if the user doesn't select something... or even just give a default value there in the first place.

    But, if you want it to work the way you're asking, you could:

    a) have the "Please select an item..." in your dictionary, then have an event handler remove it when the user selects something else

    b) have the "Please select an item..." as the only item in your bound dictionary, then have an event handler change the binding when the user opens the combo box

    c) put a label ontop of the combo box with a transparent background that, when clicked on, disappears

    d) (untested), how about adjusting the code from this link?:

    <ComboBox IsTextSearchEnabled="True" StaysOpenOnEdit="True" 
              Width="150" Height="24"  IsReadOnly="False" IsEditable="True">
      <ComboBox.Resources>
        <VisualBrush x:Key="HelpBrush" TileMode="None" Opacity="0.4" Stretch="None" AlignmentX="Left">
          <VisualBrush.Visual>
            <TextBlock FontStyle="Italic" Text="Type or select from list"/>
          </VisualBrush.Visual>
        </VisualBrush>
      </ComboBox.Resources>
      <ComboBox.Style>
        <Style TargetType="ComboBox">
          <Style.Triggers>
            <Trigger Property="Text" Value="{x:Null}">
              <Setter Property="Background" Value="{StaticResource HelpBrush}"/>
            </Trigger>
            <Trigger Property="Text" Value="">
              <Setter Property="Background" Value="{StaticResource HelpBrush}"/>
            </Trigger>
          </Style.Triggers>
        </Style>
      </ComboBox.Style>
      <ComboBoxItem>First item</ComboBoxItem>
      <ComboBoxItem>Another item</ComboBoxItem>
    </ComboBox>