Проблема с привязкой значения Nullable к WPF ComboBox - PullRequest
4 голосов
/ 18 марта 2009

Я связываю WPF ComboBox со значением типа MyEnum? (где MyEnum является перечисляемым типом)

Я программно заполняю элементы ComboBox следующим образом:

// The enum type being bound to 
enum MyEnum { Yes, No }

// Helper class for representing combobox listitems
// (a combination of display string and value)
class ComboItem {
  public string Display {get;set}
  public MyEnum? Value {get;set}
}

private void LoadComboBoxItems()
{
  // Make a list of items to load into the combo
  var items = new List<ComboItem> {
    new ComboItem {Value = null, Display = "Maybe"},
    new ComboItem {Value = MyEnum.Yes, Display = "Yes"},
    new ComboItem {Value = MyEnum.No, Display = "No"},};

  // Bind the combo's items to this list.
  theCombo.ItemsSource = items;
  theCombo.DisplayMemberPath = "Display";
  theCombo.SelectedValuePath = "Value";
}

Также в коде позади я устанавливаю DataContext для экземпляра класса со свойством TheNullableProperty (для этого примера в любом случае) типа MyEnum?.

Привязка SelectedValue для Combo выполняется в моем файле XAML.

<ComboBox 
  Name="theCombo" 
  SelectedValue="{Binding Path=TheNullableProperty,
                          UpdateSourceTrigger=PropertyChanged}"/>

Проблема:

Если значение свойства привязки изначально не равно нулю, поле со списком отображает значение правильно.

Но когда значение привязанного свойства изначально равно нулю, поле со списком остается пустым.

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

Например: вы можете выбрать Возможно из выпадающего списка, и свойство привязки будет правильно установлено на ноль. Это просто первоначальная загрузка, которая не удалась. Может быть, мне нужно просто вручную установить SelectedValue ...

Что я закончил делать

  • Добавьте скрытую границу данных текстового блока к базовому значению перечисляемого значения, допускающего обнуляемое значение, с помощью преобразователя, который преобразует перечисляемое в значение обнуляемого перечисления в строку (enum.ToString или "null").
  • Загрузите поле со списком 'ComboItems', каждое из которых имеет строку Label (отображается в комбинированном списке) и строку Value, равную значениям перечисления в виде строк (и "null" для значения NULL).
  • Привязка данных со списком к текстовому блоку.

    /// <summary>
    /// Convert from EnumeratedType? to string (null->"null", enum values->ToString)
    /// </summary>
    public class EnumConverter<T> : IValueConverter where T:struct 
    {
      public static string To(T? c)
      {
        if (c == null)
          return "null";
        return c.ToString();
      }
    
      public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
      {
        return To((T?)value);
      }
    
      public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
      {
        var s = (string) value;
        if (s == "null")
          return null;
        return (T?)Enum.Parse(typeof(T), s);
      }
    }
    
    public class MyEnumConverter : EnumConverter<MyEnum>
    {
    }
    
    public class ComboItem
    {
      public string Value { get; set; }
      public string Label { get; set; }
    
      public ComboItem(MyEnum? e, string label)
      {
        Value = MyEnumConverter.To(e);
        Label = label;
      }
    }
    
    static IEnumerable<ComboItem> GetItems()
    {
      yield return new ComboItem(null, "maybe");
      yield return new ComboItem(MyEnum.Yes, "yup");
      yield return new ComboItem(MyEnum.No, "nope");
    }
    
    private void SetupComboBox()
    {
      thecombo.ItemsSource = GetItems().ToList();
    }
    

Ответы [ 5 ]

5 голосов
/ 21 марта 2009

Вы не можете привязать к нулевому значению путем разработки в WPF (по крайней мере, 3.5 SP1). Это означает, что в тот момент, когда Source получает значение Null в качестве значения, ваша привязка будет автоматически прервана и не будет работать, даже если вы укажете действительное значение для Source. Вам нужно предоставить какой-то «сердцебиительный» механизм для привязки через Value Converter. Таким образом, этот конвертер преобразует нулевое значение в некоторое «неопределенное» (не нулевое) для целей и затем может преобразовать ваше «неопределенное» обратно в нулевое ...

2 голосов
/ 18 марта 2009

Кажется, есть много проблем с тем, чтобы null было допустимым значением для ComboBox или ListBox, так как подобные вопросы задавались здесь , здесь и здесь .

Не было никакого превосходного, убивающего людоеда ответа ни на один из них.

Мое собственное предложение - добавить Maybe в качестве члена MyEnum. Я знаю, что это всего лишь пример, но если все, что имеет MyEnum, имеет значение nullable, то, возможно, MyEnum должно иметь член Undefined (или что-то подобное), в любом случае это довольно часто встречается в enums.

1 голос
/ 19 января 2011

Поле DependencyProperty.UnsetValue

using System;

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

namespace MyConverters
{
  [ValueConversion(typeof(DateTime), typeof(String))]
  public class StringToIntConverter : IValueConverter
  {
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
      int number;

      return int.TryParse(value.ToString(), out number) ? number : DependencyProperty.UnsetValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
      return value.ToString();
    }
  }
}
1 голос
/ 24 ноября 2009

Я нашел это решение онлайн, которое я считаю довольно колода. Я не совсем понимаю реализацию - это довольно серьезное .NET кунг-фу - но это здорово с моей точки зрения как пользователя. Попробуйте:

http://philondotnet.wordpress.com/2009/09/18/how-to-select-null-none-in-a-combobox-listbox-listview/

0 голосов
/ 26 мая 2017

Вот очень простое решение этой проблемы:

Вместо того, чтобы иметь элемент со значением null в вашем ItemsSource, используйте DbNull.Value как элемент или как свойство значения элемента.

Я подробно описал этот подход здесь: https://stackoverflow.com/a/44170898/6713814

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