How to set SelectedItem of a ComboBox when item is not part of the ItemsSource collection?

让人想犯罪 __ 提交于 2019-12-07 18:20:00

问题


Following scenario:

<ComboBox ItemsSource="{Binding Path=Names}"
          SelectedItem="{Binding Path=Name, UpdateSourceTrigger=PropertyChanged}">
</ComboBox>

Names is a string collection which might change through code in the ViewModel. For example Names could be set to either male names (John, Paul, George) or female names (Mary, Jane, Karen).

Let's assume the male collection is active and the user selects "John" making it the SelectedItem. Now the collection changes to female names. By default the SelectedItem will be set to Null and John will not be displayed anymore. Instead an empty string will be displayed.

What I would like to achieve is that "John" is still visible as SelectedItem although it is not in the collection anymore. However as it is not part of the collection I would like to change the color of the SelectedItem to red.

I have played around with the IsEditable property, but didn't like the changing appearance of the ComboBox. The user should not be able to enter text manually anyway.

I tried to use different templates and styles (e.g. Template, ItemTemplate, ItemContainerStyle), but didn't find a way to use it to my favour.

Is it possible to style the provided ComboBox the way I need it or do I have to create my own user control?

EDIT: I have found a solution I can live with.

<ComboBox IsEditable="True" IsReadOnly="True"
          ItemsSource="{Binding Path=Names}"
          Text="{Binding Path=Name}">
  <ComboBox.Style>
    <Style TargetType="{x:Type ComboBox}">
      <Style.Triggers>
        <DataTrigger Binding="{Binding Path=IsNameInCollection}" Value="False">
          <Setter Property="Foreground" Value="Red"/>
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </ComboBox.Style>
  <ComboBox.ItemContainerStyle>
    <Style TargetType="{x:Type ComboBoxItem}">
      <Setter Property="Foreground" Value="Black"/>
    </Style>
  </ComboBox.ItemContainerStyle>
</ComboBox>

In the ViewModel I make sure that the Name property does not change when the Names collection changes. The boolean property IsNameInCollection will be updated when the Name property or the collection changes.


回答1:


Note: this no a real, working answer / solution, but just some thoughts you might find worth to consider:

First, the SelectedItem will always change to null if the collection changes (either by replacing it with a new collection or clearing and refilling it). So as you are binding to Name property of some object, can you prevent that property from being overridden with null there internally? That way the value might not change in the ComboBox (maybe you also need TwoWayBinding for Name to make the value stick; or even firing a change event, but that depends on some testing).

Second, the rendering needs to change, so the easiest way would be to use the ItemTemplate and a custom IValueConverter implementation to convert the information of the special entry with different color / style. But the downside of this is, that the ItemTemplate will normally be used for every entry, including the current selected.

One way to deal with this is to use an ItemTemplateSelector like described here: http://www.wpftutorial.net/datatemplates.html (section "How to use a DataTemplateSelector to switch the Template depending on the data")

Another way would be to use a container instead of plain string. That container would also hold a boolean value to indicte a different rendering. That boolean value could be used in the ItemTemplate. But in this scenario you need to wrap all string values.

Third, how should the ComboBox react if the selected value is still the old value that is not in the current list, and then the user selects another value. One logic would be that the old value just disappears, but then the user cannot select it back. If it should be still available in the list, then you must somehow add it to the list of current values, but mark it that it is a special value. In both cases you also need a logic that detects later if a value was chosen that is not valid according to the current available list.

I hope this helps to find a working solution.



来源:https://stackoverflow.com/questions/10267769/how-to-set-selecteditem-of-a-combobox-when-item-is-not-part-of-the-itemssource-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!