Mat*_*ton 42 data-binding wpf combobox
在WPF中,似乎无法从ComboBox中选择(使用鼠标)"null"值.编辑为了澄清,这是.NET 3.5 SP1.
这是一些显示我的意思的代码.首先,C#声明:
public class Foo
{
    public Bar Bar { get; set; }
}
public class Bar 
{
    public string Name { get; set; }
}
接下来,我的Window1 XAML:
<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <StackPanel>
        <ComboBox x:Name="bars" 
                  DisplayMemberPath="Name" 
                  Height="21" 
                  SelectedItem="{Binding Bar}"
                  />
    </StackPanel>
</Window>
最后,我的Window1类:
public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
        bars.ItemsSource = new ObservableCollection<Bar> 
        {
            null, 
            new Bar { Name = "Hello" }, 
            new Bar { Name = "World" } 
        };
        this.DataContext = new Foo();
    }
}
与我一起?我有一个ComboBox,其项目绑定到Bar实例列表,其中一个为null.我已将窗口绑定到Foo的实例,并且ComboBox正在显示其Bar属性的值.
当我运行这个应用程序时,ComboBox以空显示开始,因为默认情况下Foo.Bar为null.没关系.如果我使用鼠标向下放下ComboBox并选择"Hello"项,那也可以.但是如果我尝试重新选择列表顶部的空项,ComboBox将关闭并返回其先前的"Hello"值!
使用箭头键选择空值按预期工作,并以编程方式设置它也可以.它只能用鼠标选择不起作用.
我知道一个简单的解决方法是让一个Bar的实例代表null并通过IValueConverter运行它,但有人可以解释为什么用鼠标选择null在WPF的ComboBox中不起作用?
Tim*_*son 15
键盘根本没有选择空"项目" - 而是取消选择前一项并且不能(可以)选择后续项目. 这就是为什么在用键盘"选择"空项后,你不能再重新选择之前选择的项目("你好") - 除了通过鼠标!
简而言之,您既不能选择也不能取消选择ComboBox中的空项.当您认为自己这样做时,您宁愿取消选择或选择上一个或新项目.
通过向ComboBox中的项添加背景,可以最好地看到这一点.当您选择"Hello"时,您会注意到ComboBox中的彩色背景,但是当您通过键盘取消选择时,背景颜色会消失.我们知道这不是null项,因为当我们通过鼠标向下放下列表时,null项实际上具有背景颜色!
从原始问题中修改的以下XAML将在项目后面放置一个LightBlue背景,以便您可以看到此行为.
<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <StackPanel>
        <ComboBox x:Name="bars" Height="21" SelectedItem="{Binding Bar}">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <Grid Background="LightBlue" Width="200" Height="20">
                        <TextBlock Text="{Binding Name}" />
                    </Grid>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
    </StackPanel>
</Window>
如果你想进一步验证,可以在ComboBox上处理SelectionChanged事件,看看"选择空项"实际上在SelectionChangedEventArgs中给出了一个空数组AddedItems,并且"用鼠标选择'Hello'取消选择空项"给出一个空数组的RemovedItems.
And*_*lov 11
好吧,我最近遇到了与ComboBox的null值相同的问题.我用两个转换器解决了这个问题:
对于ItemsSource属性:它用转换器参数中传递的任何值替换集合中的空值:
class EnumerableNullReplaceConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var collection = (IEnumerable)value;
        return
            collection
            .Cast<object>()
            .Select(x => x ?? parameter)
            .ToArray();
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}
对于SelectedValue属性:这个属性相同,但对于单个值和两种方式:
class NullReplaceConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value ?? parameter;
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value.Equals(parameter) ? null : value;
    }
}
使用示例:
<ComboBox 
    ItemsSource="{Binding MyValues, Converter={StaticResource EnumerableNullReplaceConverter}, ConverterParameter='(Empty)'}" 
    SelectedValue="{Binding SelectedMyValue, Converter={StaticResource NullReplaceConverter}, ConverterParameter='(Empty)'}"
    />
结果:

注意:如果绑定到ObservableCollection,则会丢失更改通知.此外,您不希望集合中有多个空值.
小智 8
我为这个问题找到了一个新的解决方案."使用Mahapps"
  xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
  <ComboBox x:Name="bars"  **controls:TextBoxHelper.ClearTextButton="True"**
              DisplayMemberPath="Name" 
              Height="21" 
              SelectedItem="{Binding Bar}"/>
您可以使用关闭按钮清除内容.
谢谢.
我知道这个答案不是你要求的(解释为什么它不适用于鼠标),但我认为这个前提是有缺陷的:
从我作为程序员和用户(而不是.NET)的角度来看,选择空值是件坏事."null"应该是缺少值,而不是你选择的东西.
如果您需要明确不选择某些内容的能力,我会建议您提到的解决方法(" - ","na"或"none"作为值)或更好
我花了一天的时间来找到有关在组合框中选择空值的问题的解决方案,最后,是的,我终于在此 url 上写的一篇文章中找到了解决方案:
public class ComboBoxEmptyItemConverter : IValueConverter 
{ 
/// <summary> 
/// this object is the empty item in the combobox. A dynamic object that 
/// returns null for all property request. 
/// </summary> 
private class EmptyItem : DynamicObject 
{ 
    public override bool TryGetMember(GetMemberBinder binder, out object result) 
    { 
        // just set the result to null and return true 
        result = null; 
        return true; 
    } 
} 
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
{ 
    // assume that the value at least inherits from IEnumerable 
    // otherwise we cannot use it. 
    IEnumerable container = value as IEnumerable; 
    if (container != null) 
    { 
        // everything inherits from object, so we can safely create a generic IEnumerable 
        IEnumerable<object> genericContainer = container.OfType<object>(); 
        // create an array with a single EmptyItem object that serves to show en empty line 
        IEnumerable<object> emptyItem = new object[] { new EmptyItem() }; 
        // use Linq to concatenate the two enumerable 
        return emptyItem.Concat(genericContainer); 
    } 
    return value; 
} 
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
{ 
    throw new NotImplementedException(); 
} 
}
 <ComboBox ItemsSource="{Binding  TestObjectCollection, Converter={StaticResource ComboBoxEmptyItemConverter}}" 
      SelectedValue="{Binding SelectedID}" 
      SelectedValuePath="ID" 
      DisplayMemberPath="Name" />