jjzjj

c# - Combobox SelectedItem 数据绑定(bind)空引用异常

coder 2023-07-13 原文

我现在对组合框有点失望,希望有人能回答我的问题。问题出在 SelectedItem 上。当我在调试器中运行我的应用程序时,如果我在 ComboBox 中输入与项目中的项目(即.. a、b 或 c)匹配的文本,然后删除该文本,它将引发空引用异常。如果我在 ComboBox 中输入的文本与 Items 中的 Item(ie.. z) 不匹配,然后删除该文本,它不会崩溃。此行为仅发生在调试器中。如果我在外面运行应用程序,我不会崩溃。我正在使用 mvvmlight takeit,但我不认为它与此有任何关系。我的代码在下面

查看:

<ComboBox IsEditable="True"
              VerticalAlignment="Top"
              ItemsSource="{Binding Items}"
              DisplayMemberPath="Name"
              SelectedItem="{Binding Item,Mode=TwoWay}"/>

型号:

public class Item
{
    public string Name { get; set; }
    public int Id { get; set; }
}

虚拟机:

public MainViewModel()
    {
        Items = new List<Item>
          {
            new Item {Name="a", Id=0},
            new Item {Name="b", Id=1},
            new Item {Name="c", Id=2},
          };
    }

    /// <summary>
    /// The <see cref="Items" /> property's name.
    /// </summary>
    public const string ItemsPropertyName = "Items";

    private List<Item> _items;

    /// <summary>
    /// Sets and gets the Items property.
    /// Changes to that property's value raise the PropertyChanged event. 
    /// </summary>
    public List<Item> Items
    {
        get
        {
            return _items;
        }
        set
        {
            Set(ItemsPropertyName, ref _items, value);
        }
    }

    /// <summary>
    /// The <see cref="Item" /> property's name.
    /// </summary>
    public const string ItemPropertyName = "Item";

    private Item _item;

    /// <summary>
    /// Sets and gets the Item property.
    /// Changes to that property's value raise the PropertyChanged event. 
    /// </summary>
    public Item Item
    {
        get
        {
            return _item;
        }
        set
        {
            Set(ItemPropertyName, ref _item, value);
        }
    }

最佳答案

这是 .NET Framework 4(和 .NET 4.5,.NET 3.0 和 .NET 3.5 中没有)中的错误。

方法 PresentationFramework.dll!MS.Internal.Data.PropertyPathWorker.DetermineWhetherDBNullIsValid(object item) 导致了这个问题。

用.NET Reflector 看,它的代码是这样的:

private bool DetermineWhetherDBNullIsValid(object item)
{
    PropertyInfo info;
    PropertyDescriptor descriptor;
    DependencyProperty property;
    DynamicPropertyAccessor accessor;
    this.SetPropertyInfo(this._arySVS[this.Length - 1].info, out info, out descriptor, out property, out accessor);
    string columnName = (descriptor != null) ? descriptor.Name : ((info != null) ? info.Name : null);
    object arg = ((columnName == "Item") && (info != null)) ? this._arySVS[this.Length - 1].args[0] : null;
    return SystemDataHelper.DetermineWhetherDBNullIsValid(item, columnName, arg);
}

问题在以下行:

object arg = ((columnName == "Item") && (info != null)) ? this._arySVS[this.Length - 1].args[0] : null;

代码假定如果 columnName"Item",则属性是索引器并尝试通过 args[0] 访问它的第一个参数这是 NullReferenceException 发生的地方,因为 argsnull 因为属性不是索引器。它恰好被命名为 "Item"

.NET 实现者应该使用 PropertyInfo.GetIndexParameters()info 上,如果返回的数组不包含零元素,则假设属性是索引器。或者使用 Binding.IndexerName用于检查(Binding.IndexerName 的值为 "Item[]")。

为什么仅在 Visual Studio 调试器中出现问题要微妙得多,它隐藏在以下方法中: PresentationFramework.dll!MS.Internal.Data.PropertyPathWorker.DetermineWhetherDBNullIsValid()

下面是反汇编代码:

private void DetermineWhetherDBNullIsValid()
{
    bool flag = false;
    object item = this.GetItem(this.Length - 1);
    if ((item != null) && AssemblyHelper.IsLoaded(UncommonAssembly.System_Data))
    {
        flag = this.DetermineWhetherDBNullIsValid(item);
    }
    this._isDBNullValidForUpdate = new bool?(flag);
}

由于 item 变量不会为 null(它实际上是 WeakReference 的一个实例,其中包含 MainViewModel 实例),只有条件 失败的方法如果加载了 System.Data.dll 程序集,则调用 DetermineWhetherDBNullIsValid(item),使用 AssemblyHelper.IsLoaded(UncommonAssembly.System_Data) 检查。

Visual Studio 调试器将始终加载 System.Data.dll,因为项目正在引用它,尽管它没有使用它。 在 Visual Studio 调试器之外,System.Data.dll 仅在使用时加载,而这从不加载,这就是应用程序在 Visual Studio 之外不会失败的原因。

您有以下选项来解决此问题:

  1. 将绑定(bind)到 ComboBox.SelectedItem 的属性重命名为 "Item" 以外的某个名称,这样有问题的 .NET 实现就不再假定该属性是索引器。
  2. 从项目引用中删除 System.Data.dll,这样即使在 Visual Studio 调试器中也不会加载它。

我发现选项 2 更脆弱,因为可能会出现必须加载 System.Data.dll 的情况,无论是直接由您的应用程序加载还是由其他加载的程序集间接加载。

所以我会选择选项 1。

关于c# - Combobox SelectedItem 数据绑定(bind)空引用异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17733338/

有关c# - Combobox SelectedItem 数据绑定(bind)空引用异常的更多相关文章

  1. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  2. ruby - ruby 中的 TOPLEVEL_BINDING 是什么? - 2

    它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput

  3. ruby-on-rails - Rails - 乐观锁定总是触发 StaleObjectError 异常 - 2

    我正在学习Rails,并阅读了关于乐观锁的内容。我已将类型为integer的lock_version列添加到我的articles表中。但现在每当我第一次尝试更新记录时,我都会收到StaleObjectError异常。这是我的迁移:classAddLockVersionToArticle当我尝试通过Rails控制台更新文章时:article=Article.first=>#我这样做:article.title="newtitle"article.save我明白了:(0.3ms)begintransaction(0.3ms)UPDATE"articles"SET"title"='dwdwd

  4. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  5. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  6. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  7. ruby - 在 Ruby 中重新分配常量时抛出异常? - 2

    我早就知道Ruby中的“常量”(即大写的变量名)不是真正常量。与其他编程语言一样,对对象的引用是唯一存储在变量/常量中的东西。(侧边栏:Ruby确实具有“卡住”引用对象不被修改的功能,据我所知,许多其他语言都没有提供这种功能。)所以这是我的问题:当您将一个值重新分配给常量时,您会收到如下警告:>>FOO='bar'=>"bar">>FOO='baz'(irb):2:warning:alreadyinitializedconstantFOO=>"baz"有没有办法强制Ruby抛出异常而不是打印警告?很难弄清楚为什么有时会发生重新分配。 最佳答案

  8. ruby - 一个 YAML 对象可以引用另一个吗? - 2

    我想让一个yaml对象引用另一个,如下所示:intro:"Hello,dearuser."registration:$introThanksforregistering!new_message:$introYouhaveanewmessage!上面的语法只是它如何工作的一个例子(这也是它在thiscpanmodule中的工作方式。)我正在使用标准的ruby​​yaml解析器。这可能吗? 最佳答案 一些yaml对象确实引用了其他对象:irb>require'yaml'#=>trueirb>str="hello"#=>"hello"ir

  9. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  10. ruby - 我如何添加二进制数据来遏制 POST - 2

    我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

随机推荐