2009-03-18 31 views
4

WPFコンボボックスをMyEnum型のnullableプロパティにバインドしていますか?私はプログラムでこのようなコンボボックスの項目移入AM(ここMyEnumが列挙型である)Nullable値をWPFコンボボックスにバインドする際の問題

:コードビハインドも

// 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?タイプのTheNullableProperty(この例ではとにかく)と呼ばれます。

ComboのSelectedValueのバインドは、私のXAMLファイルで行われます。

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

問題:

バウンドプロパティの値は、最初は非nullで、コンボボックスが正しく値を表示します。

ただし、バインドされたプロパティの値が最初はnullの場合、コンボボックスは空白です。

コンボボックスが最初に表示されたときに、データバインディングのすべての側面がnull値の表記とは別の働きをしているようです。

たとえば、ドロップダウンから[多分]を選択すると、バインドされたプロパティが正しくnullに設定されます。最初のローディングが失敗しただけです。たぶん私はちょうど手動で最初にSelectedValueのを設定し...私は

  • をやってしまった何

    がNULL可能に列挙型から変換コンバータを介して基本的なNULL可能列挙値に隠されたテキストブロックデータバインドを追加する必要がありますstring(enum.ToString、または "null")。

  • コンボボックスには、文字列Label(コンボで表示)と文字列(文字列としての列値)(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を値として取得すると、Bindingは自動的に壊れてしまい、Sourceに有効な値を指定しても機能しません。バリューコンバーターを使用してバインディングを行うためには、「ハートビート」の仕組みを提供する必要があります。そのため、コンバータはヌル値をターゲットに対して「未定義」(非ヌル)に変換し、「未定義」をヌルに変換することができます。

+1

nullはItemsControlsの場合の特別な値だと思います。コンバータを提供している間は、例えばTextBlockにnullをバインドできます。 Aコンバーターは、ItemsControlsが選択された項目としてAFAICSを受け入れることを助けるものではありません。 – mackenir

2

ヌルを持つ多くの問題をがあるように思われる同様の質問がhereherehereを依頼されているとして、ComboBoxまたはListBoxの有効な値です。

これらのどれに対しても素晴らしい、鬼畜殺しの答えはありませんでした。

私自身の提案は、MyEnumのメンバーとしてMaybeを追加することです。私はそれが単なる例だと知っていますが、MyEnumのすべてがnullableである場合、MyEnumUndefinedのメンバー(またはそれに類するもの)を持つ必要があります。これはenumsとよく似ています。

+0

この場合MyEnumをXSDから生成され、に結合しているタイプ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プロパティとして使用します。

私はここでは詳細にこの方法を説明:https://stackoverflow.com/a/44170898/6713814

関連する問題