以下情景:
<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 。
答案 0 :(得分:1)
注意:这不是一个真实的,有效的答案/解决方案,但只是您可能会发现一些值得考虑的想法:
首先,如果集合发生更改(通过将其替换为新集合或清除并重新填充),SelectedItem
将始终更改为null。因此,当您绑定到某个对象的Name
属性时,是否可以在内部阻止该属性被null覆盖?这样,ComboBox中的值可能不会改变(也许您还需要Name
的TwoWayBinding来使值保持不变;或者甚至触发更改事件,但这取决于某些测试)。
其次,渲染需要更改,因此最简单的方法是使用ItemTemplate
和自定义IValueConverter
实现来转换具有不同颜色/样式的特殊条目的信息。但缺点是,ItemTemplate
通常会用于每个条目,包括当前选择的条目。
处理此问题的一种方法是使用此处所述的ItemTemplateSelector
:http://www.wpftutorial.net/datatemplates.html(“如何根据数据使用DataTemplateSelector切换模板”一节)
另一种方法是使用容器而不是普通字符串。该容器还将保存一个布尔值以指示不同的呈现。该布尔值可以在ItemTemplate
中使用。但在这种情况下,您需要包装所有字符串值。
第三,如果所选值仍然是当前列表中不存在的旧值,则ComboBox应该如何反应,然后用户选择另一个值。一个逻辑是旧值刚刚消失,但用户无法选择它。如果它仍然可以在列表中使用,那么您必须以某种方式将其添加到当前值列表中,但标记它是一个特殊值。在这两种情况下,您还需要一个逻辑,以便稍后根据当前可用列表选择一个无效的值。
我希望这有助于找到一个有效的解决方案。