0

我在 wpf 中有一个 ComboBox,它在视图和视图模型之间双向绑定。在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”)。这是合法的,但可能不是您想要的。该路径应用于 ItemsSource 中的项目,其类型为 ItemsOrderByItem;此类型没有名为“名称”的属性。

  4. ItemsOrderByItem 类具有可变的相等语义,即对于固定对象 x 和 y,Object.Equals(x, y) 的结果可以改变。这是因为 Equals 方法依赖于一个公开可变的字段 - EnumObject。这将混淆任何(合法地)假设一旦 x 和 y 测试 Equal,它们将保持 Equal 的代码。

  5. 该类覆盖 Equals,但不覆盖 GetHashCode。这是被禁止的(请参阅任何一种方法的文档),因为每当在哈希表中使用实例时,它都会导致可怕的混乱。两个相等但具有不同哈希码的实例将破坏哈希表。[当你解决这个问题时,请记住确保对象的哈希码永远不会改变 - 这也是一个记录的要求。]

其中,最后一个可能对您的问题负有最大责任。WPF 使用哈希表来帮助表示选定项的集合,并且在 v4.5 中确切的用法已经改变。ItemsOrderByItem 类的不可靠散列行为很可能导致混淆。

如果修复这些编码问题仍然不能解决您的问题,请随时打开与 repro 项目的连接错误。

于 2012-08-22T21:05:03.167 回答