绑定的Silverlight Combobox未显示EnumBinder的默认值

时间:2011-09-20 15:52:45

标签: silverlight xaml binding combobox enums

我的模型使用枚举进行固定的多项选择。我在http://deanchalk.me.uk/post/Enumeration-Binding-In-Silverlight.aspx使用Dean Chalk的EnumBinder绑定到一个组合框。除了未显示默认值外,一切似乎都很好用。所选索引为-1,如果我绑定到SelectedItem或SelectedValue则无关紧要。组合框效果很好。我对使用任何其他绑定组合框的默认值没有任何问题。

enumbindingsupport.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;

/* All of this was once just part of the RichClient sub-namespace
 * but it has its uses elsewhere, so it has been moved. 
 */

/// <summary>
/// Container for enumeration values.
/// </summary>
/// <remarks>
/// http://deanchalk.me.uk/post/Enumeration-Binding-In-Silverlight.aspx
/// </remarks>
public sealed class EnumContainer
{
    public int EnumValue { get; set; }
    public string EnumDescription { get; set; }
    public object EnumOriginalValue { get; set; }
    public override string ToString() {
        return EnumDescription;
    }

    public override bool Equals(object obj) {
        if (obj == null)
            return false;
        if (obj is EnumContainer)
            return EnumValue.Equals((int)((EnumContainer)obj).EnumValue);
        return EnumValue.Equals((int)obj);
    }

    public override int GetHashCode() {
        return EnumValue.GetHashCode();
    }

}

/// <summary>
/// A collection to store a list of EnumContainers that hold enum values.
/// </summary>
/// <remarks>
/// http://deanchalk.me.uk/post/Enumeration-Binding-In-Silverlight.aspx
/// </remarks>
/// <typeparam name="T"></typeparam>
public class EnumCollection<T> : List<EnumContainer> where T : struct
{
    public EnumCollection() {
        var type = typeof(T);
        if (!type.IsEnum)
            throw new ArgumentException("This class only supports Enum types");
        var fields = typeof(T).GetFields(BindingFlags.Static | BindingFlags.Public);
        foreach (var field in fields) {
            var container = new EnumContainer();
            container.EnumOriginalValue = field.GetValue(null);
            container.EnumValue = (int)field.GetValue(null);
            container.EnumDescription = field.Name;
            var atts = field.GetCustomAttributes(false);
            foreach (var att in atts)
                if (att is DescriptionAttribute) {
                    container.EnumDescription = ((DescriptionAttribute)att).Description;
                    break;
                }
            Add(container);
        }

    }
}

enumvalueconverter.cs

using System;
using System.Globalization;
using System.Windows.Data;

/// <summary>
/// Supports two-way binding of enumerations.
/// </summary>
public class EnumValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter,
                            CultureInfo culture) {
        return (int)value;
    }

    public object ConvertBack(object value, Type targetType, object parameter,
                            CultureInfo culture) {
        if (value == null)
            return null;
        if (value.GetType() == targetType)
            return value;
        return ((EnumContainer)value).EnumOriginalValue;
    }
}

使用的枚举:

/// <summary>
/// Describes the available sorting options.
/// </summary>
public enum PeopleSortOptionsEnum
{

    [Display(Order = 10)]
    [Description("First Name, Last Name")]
    FirstNameThenLastName,

    [Display(Order = 20)]
    [Description("Last Name, First Name")]
    LastNameThenFirstName,

    [Display(Order = 30)]
    Grade,

    [Display(Order = 40)]
    Gender,

    [Display(Order = 50)]
    Age
}
我模特的

属性:

    /// <summary>
    /// This is the list for the enumeration to bind to.
    /// </summary>
    public EnumCollection<PeopleSortOptionsEnum> AvailableSortOptions
    {
        get { return new EnumCollection<PeopleSortOptionsEnum>(); }
    }

XAML片段:

    <ComboBox ItemsSource="{Binding Path=AvailableSortOptions, Mode=OneWay}" SelectedValue="{Binding Path=Preferences.SortOrder, Mode=TwoWay, Converter={StaticResource EnumConverter}}" Grid.Column="1" Grid.Row="2" Height="32" Margin="48,31,0,0" x:Name="cboSort" VerticalAlignment="Top" />

如果Preferences.SortOrder的类型为PeopleSortOptionsEnum,则转换器在我的app.xaml中作为所有枚举类型的转换器。

任何人都知道为什么它不会将索引设置为当前选定的值?我即将在代码隐藏中抛出一些代码,将selectedindex设置为加载时当前选择的值,但考虑到它,我觉得很脏。

除了这个问题,它的效果非常好,所以感谢Dean!

修改添加Preferences.SortOrder代码:

public PeopleSortOptionsEnum SortOrder 
{ 
  get { return sortOrder; } 
  set 
  { 
    if (sortOrder != value) 
    { 
      sortOrder = value; 
      PropertyHasChanged("SortOrder"); 
    } 
  } 
}

1 个答案:

答案 0 :(得分:0)

问题是你的枚举转换器类上的Convert方法:

public object Convert(object value, Type targetType, object parameter,
                        CultureInfo culture) {
    return (int)value;
}

当组合框SelectedItem从SortOrder获取值时,它返回Enum值,该转换器将转换为int。但是,组合框项是EnumContainer对象的集合,而不是整数。因此无法设置所选项目。

要解决此问题,您必须做两件事。首先更改组合框绑定并设置SelectedValuePath:

<ComboBox ItemsSource="{Binding Path=AvailableSortOptions}" 
          SelectedValue="{Binding Path=SortOrder, Mode=TwoWay, Converter={StaticResource EnumConverter}}" 
          SelectedValuePath="EnumOriginalValue"/>

其次,您必须稍微修改转换器上的Convert方法:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
  return value;
}

一旦我做了这两个更改,它就开始按预期工作了。

相关问题