WPF привязка ComboBox к перечислению (со скручиванием)

Если возможно удалить wamp, запустите установку от имени администратора, а затем измените файл mysql.conf следующим образом

<Directory "c:/wamp/apps/phpmyadmin3.5.1/">
    Options Indexes FollowSymLinks MultiViews
    AllowOverride all
        Order Allow,Deny
    Allow from all
    Allow from all
</Directory>

Нет: до переустановки в качестве администратора решение, описанное выше, у меня не сработало

14
задан Dave Clemmer 31 July 2011 в 00:58
поделиться

5 ответов

Мне нравится, как ты думаешь. Но GetCustomAttributes использует отражение. Что это повлияет на вашу производительность?

Посмотрите этот пост: WPF - отображение перечислений в элементе управления ComboBox http://www.infosysblogs.com/microsoft/2008/09/wpf_displaying_enums_in_combob.html

6
ответ дан 1 December 2019 в 07:06
поделиться

Помимо вопросов об использовании отражения и атрибутов, есть несколько способов сделать это, но я думаю, что лучший способ - просто создать небольшой класс модели представления, который обертывает значение перечисления:

public class ModeViewModel : ViewModel
{
    private readonly Mode _mode;

    public ModeViewModel(Mode mode)
    {
        ...
    }

    public Mode Mode
    {
        get { ... }
    }

    public string Description
    {
        get { return _mode.GetDescription(); }
    }
}

​​В качестве альтернативы вы можете изучить использование ObjectDataProvider .

3
ответ дан 1 December 2019 в 07:06
поделиться

Я бы предложил DataTemplate и ValueConverter. Это позволит вам настроить способ его отображения, но вы все равно сможете прочитать свойство SelectedItem поля со списком и получить фактическое значение перечисления.

ValueConverters требует большого количества шаблонного кода, но здесь нет ничего слишком сложного. Сначала вы создаете класс ValueConverter:

public class ModeConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter,
        CultureInfo culture)
    {
        return ((Mode) value).GetDescription();
    }
    public object ConvertBack(object value, Type targetType, object parameter,
        CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

Поскольку вы конвертируете только значения перечисления в строки (для отображения), вам не нужен ConvertBack - это только для сценариев двустороннего связывания.

Затем вы помещаете экземпляр ValueConverter в свои ресурсы, примерно так:

<Window ... xmlns:WpfApplication1="clr-namespace:WpfApplication1">
    <Window.Resources>
        <WpfApplication1:ModeConverter x:Key="modeConverter"/>
    </Window.Resources>
    ....
</Window>

Затем вы готовы предоставить ComboBox DisplayTemplate, который форматирует его элементы с помощью ModeConverter:

<ComboBox Name="comboBox" ...>
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Converter={StaticResource modeConverter}}"/>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

Чтобы проверить это, я также добавил метку, которая покажите мне фактическое значение SelectedItem, и он действительно показал, что SelectedItem является перечислением, а не отображаемым текстом, чего я хотел бы:

<Label Content="{Binding ElementName=comboBox, Path=SelectedItem}"/>
20
ответ дан 1 December 2019 в 07:06
поделиться

Я предлагаю вам использовать расширение разметки, которое я уже опубликовал здесь , с небольшими изменениями:

[MarkupExtensionReturnType(typeof(IEnumerable))]
public class EnumValuesExtension : MarkupExtension
{
    public EnumValuesExtension()
    {
    }

    public EnumValuesExtension(Type enumType)
    {
        this.EnumType = enumType;
    }

    [ConstructorArgument("enumType")]
    public Type EnumType { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if (this.EnumType == null)
            throw new ArgumentException("The enum type is not set");
        return Enum.GetValues(this.EnumType).Select(o => GetDescription(o));
    }
}

Затем вы можете использовать его следующим образом:

<ComboBox ItemsSource="{local:EnumValues local:Mode}"/>

EDIT : предложенный мной метод будет привязываться к списку строк, что нежелательно, поскольку мы хотим, чтобы SelectedItem имел тип Mode. Было бы лучше удалить часть .Select (...) и использовать привязку с настраиваемым преобразователем в ItemTemplate.

3
ответ дан 1 December 2019 в 07:06
поделиться

Вот как я делаю это с помощью MVVM. На моей модели я бы определил свой enum:

    public enum VelocityUnitOfMeasure
    {
        [Description("Miles per Hour")]
        MilesPerHour,
        [Description("Kilometers per Hour")]
        KilometersPerHour
    }

На моей ViewModel я выставляю свойство, которое предоставляет возможные варианты выбора в виде строки, а также свойство для получения/установки значения модели. Это полезно, если мы не хотим использовать каждое значение enum в типе:

    //UI Helper
    public IEnumerable<string> VelocityUnitOfMeasureSelections
    {
        get
        {
            var units = new []
                            {
                               VelocityUnitOfMeasure.MilesPerHour.Description(),
                               VelocityUnitOfMeasure.KilometersPerHour.Description()
                            };
            return units;
        }
    }

    //VM property
    public VelocityUnitOfMeasure UnitOfMeasure
    {
        get { return model.UnitOfMeasure; }
        set { model.UnitOfMeasure = value; }
    }

Кроме того, я использую общий EnumDescriptionCoverter:

public class EnumDescriptionConverter : IValueConverter
{
    //From Binding Source
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (!(value is Enum)) throw new ArgumentException("Value is not an Enum");
        return (value as Enum).Description();
    }

    //From Binding Target
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (!(value is string)) throw new ArgumentException("Value is not a string");
        foreach(var item in Enum.GetValues(targetType))
        {
            var asString = (item as Enum).Description();
            if (asString == (string) value)
            {
                return item;
            }
        }
        throw new ArgumentException("Unable to match string to Enum description");
    }
}

И, наконец, с представлением я могу сделать следующее:

<Window.Resources>
    <ValueConverters:EnumDescriptionConverter x:Key="enumDescriptionConverter" />
</Window.Resources>
...
<ComboBox SelectedItem="{Binding UnitOfMeasure, Converter={StaticResource enumDescriptionConverter}}"
          ItemsSource="{Binding VelocityUnitOfMeasureSelections, Mode=OneWay}" />
7
ответ дан 1 December 2019 в 07:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: