0

ビューとビューモデルの間で双方向にバインドする ComboBox が wpf にあります。win7 の .net 4 で実行すると、すべてが期待どおりに動作しましたが、Windows 8 でアプリケーションを実行すると、コンボボックスがビューモデルから正しい選択項目を取得できないようです。

ビューに入ると、コンボボックスはビューモデルから選択されたアイテムを要求します
。選択されたアイテムが返され、「Equals」をオーバーライドする私のメソッドはtrueを返します。
ビューのコンボボックスは、これを登録しないか、登録してから無視し、次に発生するのは、ビューがビューモデルの「選択された項目」を「NULL」に設定することです。

要件を達成できる別の方法はありますか、それとも.net 4.5の下で.net 4アプリを実行する際の単なるバグですか?

これがソースです。: 列挙型ではなくアイテム クラスに直接バインドするので、[Description] タグにアクセスして、コンボ ボックス内のより適切なアイテム名を取得できます。

意見

<Controls:KNComboBox Style="{DynamicResource FlowMenuComboBox}" SelectedItem="{Binding ItemsOrder}" ItemsSource="{Binding ItemsOrderValues}" Margin="10,0,0,10"
                                             DisplayMemberPath="Description" SelectedValuePath="{Binding Path=EnumObject}" DisplayString="Sort By:"/>

モデルを見る

private ItemsOrderByItem _itemsOrder;
    public ItemsOrderByItem ItemsOrder
    {
        get
        {
            return _itemsOrder;
        }
        set
        {
            _itemsOrder = value;
            RaisePropertyChanged("ItemsOrder");
            //Methods Called Here Not Important To Question
        }
    }
    public List<ItemsOrderByItem> ItemsOrderValues
    {
        get
        {
            List<ItemsOrderByItem> enumItems = new List<ItemsOrderByItem>();
            foreach (ItemsOrderBy enumValue in Enum.GetValues(typeof(ItemsOrderBy)))
            {
                enumItems.Add(new ItemsOrderByItem(enumValue));
            }
            return enumItems;
        }
    }

列挙型

public enum ItemsOrderBy
{
    [Description("Name")]
    Name,
    [Description("Date Added")]
    DateAdded        
}

アイテム クラス

public class ItemsOrderByItem
{
    public ItemsOrderByItem(ItemsOrderBy enumValue)
    {
        EnumObject = enumValue;
    }
    public ItemsOrderBy EnumObject;
    public string Description
    {
        get
        {
            return EnumExtension.GetEnumDescription<ItemsOrderBy>(EnumObject);
        }
    }

    public override string ToString()
    {
        return Description;
    }

    public override bool Equals(object obj)
    {
        if (obj is ItemsOrderByItem)
        {
            return ((ItemsOrderByItem)obj).EnumObject == EnumObject;
        }
        else
        {
            return false;
        }
    }
}  
4

1 に答える 1

1

投稿のコード スニペットを調べると、いくつかの問題が明らかになります。

  1. ItemsOrderValues プロパティは、クエリが実行されるたびに新しい値を返します。これは、プロパティ変更通知を発生させずに値を変更することと同じです。データ バインディング クライアントは混乱します。

  2. {Binding Path=EnumObject} は機能しません。バインディング パスはプロパティを使用します。EnumObject はフィールドです。

  3. SelectedValuePath の型は文字列です。EnumObject へのバインド (機能した場合) は、ItemsOrderBy 型のオブジェクトを生成します。型変換後、SelectedValuePath が "Name" (または "ItemsOrderBy.Name") に設定されます。これは合法ですが、おそらくあなたが望んでいたものではありません。パスは、タイプが ItemsOrderByItem の ItemsSource 内のアイテムに適用されます。この型には「名前」というプロパティがありません。

  4. ItemsOrderByItem クラスには、変更可能な等値セマンティクスがあります。つまり、固定オブジェクト x および y に対して、Object.Equals(x, y) の結果が変化する可能性があります。これは、Equals メソッドがパブリックに変更可能なフィールドである EnumObject に依存しているためです。これは、x と y が等しいとテストされた後は等しいままであると (正当に) 想定しているコードを混乱させます。

  5. このクラスは Equals をオーバーライドしますが、GetHashCode をオーバーライドしません。インスタンスがハッシュテーブルで使用されるたびに恐ろしい混乱を招くため、これは禁止されています (いずれかの方法についてはドキュメントを参照してください)。等しいがハッシュコードが異なる 2 つのインスタンスは、ハッシュテーブルを破損します。[これを修正するときは、オブジェクトのハッシュコードが決して変更されないようにすることを忘れないでください。これは文書化された要件でもあります。]

これらのうち、最後のものはおそらくあなたの問題に最も責任があります. WPF はハッシュテーブルを使用して、選択された項目のセットを表すのに役立ちます。正確な使用法は v4.5 で変更されました。ItemsOrderByItem クラスの信頼できないハッシュ動作が混乱を引き起こしている可能性が非常に高いです。

これらのコーディングの問題を修正しても問題が解決しない場合は、repro プロジェクトで connect bug を開いてください。

于 2012-08-22T21:05:03.167 に答える