当item不是ItemsSource集合的一部分时,如何设置ComboBox的SelectedItem?

时间:2012-04-22 12:03:45

标签: wpf colors combobox selecteditem

以下情景:

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

Names是一个字符串集合,可能会通过ViewModel中的代码进行更改。例如,名字可以设置为男性名字(约翰,保罗,乔治)或女性名字(玛丽,简,凯伦)。

假设男性集合处于活动状态,用户选择“John”使其成为SelectedItem。现在收藏品改为女性名字。默认情况下,SelectedItem将设置为Null,John将不再显示。而是显示一个空字符串。

我想要实现的是“John”仍然作为SelectedItem可见,尽管它不再在集合中。但是因为它不是集合的一部分,所以我想将SelectedItem的颜色更改为红色。

我玩过IsEditable属性,但不喜欢ComboBox外观的变化。用户无论如何都不能手动输入文本。

我尝试使用不同的模板和样式(例如Template,ItemTemplate,ItemContainerStyle),但没有找到一种方法来使用它对我有利。

是否可以按照我需要的方式设置提供的ComboBox样式,还是必须创建自己的用户控件?

编辑: 我找到了一个可以忍受的解决方案。

<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>

在ViewModel中,我确保 Names 集合更改时 Name 属性不会更改。当 Name 属性或集合发生更改时,将更新布尔属性 IsNameInCollection

1 个答案:

答案 0 :(得分:1)

注意:这不是一个真实的,有效的答案/解决方案,但只是您可能会发现一些值得考虑的想法:

首先,如果集合发生更改(通过将其替换为新集合或清除并重新填充),SelectedItem将始终更改为null。因此,当您绑定到某个对象的Name属性时,是否可以在内部阻止该属性被null覆盖?这样,ComboBox中的值可能不会改变(也许您还需要Name的TwoWayBinding来使值保持不变;或者甚至触发更改事件,但这取决于某些测试)。

其次,渲染需要更改,因此最简单的方法是使用ItemTemplate和自定义IValueConverter实现来转换具有不同颜色/样式的特殊条目的信息。但缺点是,ItemTemplate通常会用于每个条目,包括当前选择的条目。

处理此问题的一种方法是使用此处所述的ItemTemplateSelectorhttp://www.wpftutorial.net/datatemplates.html(“如何根据数据使用DataTemplateSelector切换模板”一节)

另一种方法是使用容器而不是普通字符串。该容器还将保存一个布尔值以指示不同的呈现。该布尔值可以在ItemTemplate中使用。但在这种情况下,您需要包装所有字符串值。

第三,如果所选值仍然是当前列表中不存在的旧值,则ComboBox应该如何反应,然后用户选择另一个值。一个逻辑是旧值刚刚消失,但用户无法选择它。如果它仍然可以在列表中使用,那么您必须以某种方式将其添加到当前值列表中,但标记它是一个特殊值。在这两种情况下,您还需要一个逻辑,以便稍后根据当前可用列表选择一个无效的值。

我希望这有助于找到一个有效的解决方案。