ComboBox 最初不 select 绑定值

ComboBox does not select binding value initially

首先,不是重复的。

TextBox 和 CheckBox 可以正常工作,只是 ComboBox 不行。

型号

internal class Word : _Model
{
    public enum Categories
    {
        Noun,
        Verb,
    }

    private Categories category;
    public Categories Category
    {
        get
        {
            return this.category;
        }
        set
        {
            this.SetProperty(ref this.category,
                             value);
        }
    }
}

通知(可以跳过阅读这部分)

internal abstract class _Model : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
    {
        if (object.Equals(storage, value))
        {
            return false;
        }
        storage = value;
        this.OnPropertyChanged(propertyName);
        return true;
    }

    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var eventHandler = this.PropertyChanged;
        if (eventHandler != null)
        {
            eventHandler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

控制(模型)

public sealed partial class WordEditor : UserControl
{
    public WordEditor()
    {
        this.Model = new Models.Word();
        this.Model.Category = Models.Word.Categories.Verb;
        this.InitializeComponent();
    }

    private Models.Word Model { get; set; }

    internal IList<KeyValuePair<Models.Word.Categories, string>> Categories { get { return new List<KeyValuePair<Models.Word.Categories, string>>() { new KeyValuePair<Models.Word.Categories, string>(Models.Word.Categories.Noun, "Noun"), new KeyValuePair<Models.Word.Categories, string>(Models.Word.Categories.Verb, "Verb") }; } }
}

绑定

<UserControl.Resources>
    <converters:AnyConverter x:Key="AnyConverter"/>
</UserControl.Resources>

<StackPanel>
    <ComboBox ItemsSource="{x:Bind Path=Categories, Mode=OneTime}"
              DisplayMemberPath="Value"
              SelectedValuePath="Key"
              SelectedValue="{x:Bind Path=Model.Category, Mode=TwoWay, Converter={StaticResource ResourceKey=AnyConverter}}"/>
</StackPanel>

转换器

internal class AnyConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        return value;
    }
}

问题

ComboBox 正确显示了 "Verb" 和 "Noun",模型正确反映了 "Verb" 或 "Noun" 上的选择。

但是,即使 Category 一开始就设置为 Verb,ComboBox 也没有显示。

如何修复它以便 ComboBox 在第一次出现时选择 "Verb"?

我重现了你的问题。这里的问题是 ComboBox.SelectedValue 不适用于枚举类型。为了测试这一点,我们可以使用不绑定的 ComboBox 并在代码隐藏中设置 SelectedValue ,如:

<ComboBox x:Name="cmb" DisplayMemberPath="Value" SelectedValuePath="Key" />

cmb.ItemsSource = Categories;
cmb.SelectedValue = Models.Word.Categories.Verb;

虽然我已经将Models.Word.Categories.Verb设置为SelectedValue,但它的值仍然是null

但是,当 Value 类型为 intstring 时有效。根据我的 WPF 经验,枚举类型也应该有效。我认为这可能是 UWP 中的一个错误。

作为变通方法,我认为您可以在 ComboBox 首次出现时使用 SelectedIndexSelectedItem 属性 至 select "Verb"。例如:

在XAML中,使用SelectedIndex代替SelectedValue

<ComboBox DisplayMemberPath="Value"
          ItemsSource="{x:Bind Path=Categories, Mode=OneTime}"
          SelectedIndex="{x:Bind Path=Model.Category, Mode=TwoWay, Converter={StaticResource ResourceKey=AnyConverter}}"
          SelectedValuePath="Key" />

并将 Converter 更改为:

internal class AnyConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        return (int)(Models.Word.Categories)value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        return (Models.Word.Categories)(int)value;
    }
}

在此之后,设置 this.Model.Category = Models.Word.Categories.Verb; 将起作用。

起初我认为@Jay Zuo - MSFT 是正确的,因为您必须将其转换为另一种形式(例如,int);然而,通过使用 SelectedItem,它起作用了!我像 OP 一样使用 SelectedValue,但没有定义 SelectedValuePath 并且它不会 select 初始值。即使不定义 SelectedValuePath 也可以绑定到 SelectedItem

请注意,如果您绑定到 SelectedItem 而不是 SelectedIndex,则完全不需要转换器。

我用 Windows 10 周年纪念版(10.0;内部版本 14393)对此进行了测试。

更新

事实证明我错了;p 为了更方便,我最终推出了自己的转换器。

public abstract class EnumToIntConverter<TEnum> : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        if (value is Enum)
            return (int)value;

        return DependencyProperty.UnsetValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        if (value is int)
            return (TEnum)value;

        return DependencyProperty.UnsetValue;
    }
}

public sealed class MyEnumToIntConverter : EnumToIntConverter<MyEnum>
{
    //Do nothing!
}

澄清一下,SelectedIndex 绝对 需要。