Связанный Silverlight Combobox не показывает значение по умолчанию с EnumBinder - PullRequest
0 голосов
/ 20 сентября 2011

Мои модели используют перечисления для фиксированного множественного выбора.Я использую EnumBinder Дина Чела, найденный в http://deanchalk.me.uk/post/Enumeration-Binding-In-Silverlight.aspx, для привязки к комбинированному списку.Кажется, все работает отлично, кроме значения по умолчанию не отображается.Выбранный индекс равен -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 на текущее выбранное значение при загрузке, но я чувствую себя таким грязным, просто думая об этом.

Помимо этой проблемы, это работает чудесно, так что спасибоДин!

Редактировать Добавление кода Preferences.SortOrder:

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

1 Ответ

0 голосов
/ 21 сентября 2011

Проблема заключается в методе Convert в вашем классе enum converter:

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

Как только я сделал эти два изменения, он начал работать как ожидалось.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...