2009-03-18 4 views
4

WPF ComboBox를 MyEnum 유형의 nullable 속성에 바인딩하고 있습니까? 에서 또한Nullable 값을 WPF 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를 설정하고있다 :

내가 프로그래밍과 같은 콤보 상자 항목을 채우는하고 (여기서 MyEnum이 열거 타입입니다) MyEnum 유형의 TheNullableProperty (이 예제의 경우 어쨌든)를 호출합니다.

Combo의 SelectedValue 바인딩은 내 XAML 파일에서 수행됩니다.

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

는 문제 :

바인딩 된 속성의 값이 처음에 null이 아닌, 콤보 상자가 제대로 값을 표시합니다.

그러나 바인딩 된 속성의 값이 처음 null이면 콤보 상자가 비어 있습니다.

콤보 상자가 처음 표시 될 때 데이터 바인딩의 모든 측면이 null 값의 표현과는 별도로 작동하는 것처럼 보입니다.

예를 들어, 드롭 다운에서 어쩌면을 선택할 수 있으며 바운드 속성이 null로 올바르게 설정됩니다. 실패한 초기 로딩 일뿐입니다. 어쩌면 난 그냥 수동으로 내가 결국 무엇

는에 null 허용 열거에서 변환하는 변환기를 통해 기본 null 허용 열거 값에 숨겨진 된 본체의 데이터 바인딩을 추가

  • 을하는 ... 처음 SelectedValue를 설정해야 string (enum.ToString 또는 "null").
  • 콤보 상자에 문자열 레이블 (콤보로 표시)과 열 (문자열 값)을 문자열 (null 값의 경우 "null")과 동일한 값을 갖는 'ComboItems'로로드하십시오.
  • 콤보 상자를 텍스트 블록에 데이터 바인딩합니다.

    /// <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(); 
    } 
    

답변

4

WPF (최소 3.5 SP1)에서 의도적으로 null 값에 바인딩 할 수 없습니다. 즉, Source가 Null을 값으로 가져 오는 순간 바인딩이 자동으로 끊어지며 소스에 유효한 값을 지정해도 작동하지 않습니다. Value Converter를 통해 바인딩을위한 "심장 박동"메커니즘을 제공해야합니다.그래서 변환기는 null 값을 대상에 대해 "Undefined"(null이 아닌)로 변환하고 "Undefined"를 null로 다시 변환 할 수 있습니다. ...

+1

ItemsControls의 경우 null이 특별한 값이라고 생각합니다. 변환기를 제공하는 한 TextBlock에 null을 바인딩 할 수 있습니다. A 변환기는 ItemsControls가 선택한 항목으로 null을 허용하도록 AFAICS를 만드는 데 도움이되지 않습니다. – mackenir

2

널 (null)을 갖는 많은 문제를 것 같다 비슷한 질문 here, herehere을 요청을받은대로, ComboBox 또는 ListBox A에 대한 유효한 값이 될 수.

그 중 어떤 것에도 훌륭한, 오우거 살해 적 대답은 없었습니다.

내 제안은 Maybe을 (를) MyEnum 회원으로 추가하는 것입니다. 나는 그것이 단지 예일 뿐이라는 것을 알고 있지만, MyEnum을 가진 모든 것이 nullable 인 경우, MyEnumUndefined 멤버 (또는 비슷한 것)를 가져야한다. 이것은 어쨌든 enums와 매우 유사하다.

+0

, 그리고 타입 MyEnum의 속성은'선택 '는 결합되고 :

은 여기 상세히 이러한 방식을 설명했다. 그것은 C#에서 속성을 나타내는 꽤 좋은 방법입니다,하지만 WPF ComboBox가 그것을 처리 할 수 ​​없다면, 내가 생각한 다른 것을해야 할 것입니다. – mackenir

1

DependencyProperty.UnsetValue Field

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(); 
    } 
    } 
} 
0

다음은이 문제에 대한 veryy 간단한 해결책이있다 : : 한번 시도해

하는 대신 ItemsSource에 널 (null) 값으로 항목을 갖는, DbNull.Value를 항목 또는 항목의 value 속성으로 사용하십시오. 그래서 널 (Null)이 존재하지 않는 속성 '이고, XSD에 생성된다이 경우 MyEnum에서 https://stackoverflow.com/a/44170898/6713814