【问题标题】:DropDownList has a SelectedValue which is invalid because it does not exist in the list of itemsDropDownList 有一个无效的 SelectedValue,因为它不存在于项目列表中
【发布时间】:2009-12-08 19:05:26
【问题描述】:

这是场景:

DropDownList 中的选择是从列出可接受值的数据库表中绑定的。在某一时间点,这些值是:

一个 二 三 四个

稍后,可接受值列表更改为:

一个 二 四 五

但是,数据库中存储下拉列表值的字段在某些行上仍包含“三”值。当加载其中一行并设置 SelectedValue 时:

dd.SelectedValue = data.Field; // where data.Field == "Three"

...抛出一个错误,说明:“dd”有一个无效的 SelectedValue,因为它不存在于项目列表中。

数据清理在这里不是一个选项。这会给客户带来问题,因为存储的值不是已经创建的数据的无效选择,而是新创建的数据的无效选择。

其他人是如何处理这种情况的?

【问题讨论】:

    标签: asp.net drop-down-menu list.selectedvalue


    【解决方案1】:

    我们这里确实有这种情况。

    发生这种情况时,我手动将缺少的项目添加到下拉列表中,但使用的是红色字体。

    如果用户尝试重新保存该项目,则红色项目被视为无效且无效。然后必须从下拉列表中选择一个有效的选项(非红色)。

    【讨论】:

    • 谢谢。到目前为止,我最喜欢这个解决方案。许多其他答案建议将此业务规则移至数据库(我不喜欢)或导致当前值不显示,这在这种情况下绝对是不可接受的。尽管在这种特殊情况下,我允许重新保存,因为该值对于以前创建的数据仍然有效。只有新数据不应该有这些值。仅在旧数据上动态添加无效值这一事实足以解决问题。
    【解决方案2】:

    假设data.Field 在这里实际上是一个字符串,我会这样做:

    ListItem itemToSelect = dd.Items.FindByText(data.Field); if(itemToSelect != null) { dd.SelectedItem = itemToSelect; }

    【讨论】:

    • 迄今为止我找到的最佳解决方案
    • 很好,+1。稍微精简的版本:dd.SelectedIndex = dd.Items.IndexOf(dd.Items.FindByValue(value));(另见this answer。)
    【解决方案3】:

    您可以在数据库表中为名为“Active”的下拉值添加一个额外的列,该列可以为真或假。然后,您无需删除旧值,而是将其标记为非活动状态。您应该有一个从客户到可接受值列表的外键约束,以确保如果仍有一些客户在使用它,您不能从表中删除值。

    在客户端中,您可以以不同的颜色显示正在使用非活动类型的客户,并具有不允许您将客户从活动类型更改为非活动类型的验证方法,但允许使用非活动类型的客户类型以保持该设置。

    【讨论】:

      【解决方案4】:

      所以旧值(在本例中为“三”)仍然存在于列表中,但只是停用了,还是完全从表中删除了?

      如果是前者,则设置两个单独的视图,一个仅包含活动项目并用于新数据输入,另一个包含所有项目并用于查看历史交易。

      【讨论】:

        【解决方案5】:

        因此,您必须将“历史上准确但现已失效”的值添加到下拉列表中,但您可以使用RequiredFieldValidator 来防止用户将此值保存回数据库。 RequiredFieldValidator's ControlToValidate 设置为您希望验证的DropDownList,然后您可以将InitialValue 属性设置为无效值。现在,在您的保存方法中,您可以在将页面保存到数据库之前检查 bool Page.IsValidRequiredFieldValidator 上的消息可能类似于 "This value is no longer acceptable due to ..."

        希望这会有所帮助!

        【讨论】:

          【解决方案6】:

          我们还有一个例程首先检查 DropDownList 中的项目,如果不存在则将其添加到列表中。与上面提到的 Danny 相同的想法,但我喜欢他将其添加为红色的额外想法。尽管想法相同,但我认为发布我们的完整例程会很有价值。它使用 foreach 遍历列表以查找值字符串。如上面 Justin 所述,使用 FindByText 可以提高效率。

          protected bool SafeSetDropDownValue(DropDownList ddl, string value, string text, bool addItemIfNotFound)
          {
              // first make sure that drop down list has been data bound so that all the options are in there
              ddl.DataBind();
          
              // look for value in the list of dropdown values
              // (can't use try/catch because exception doesn't happen until later)
              bool found = false;
              bool selected = true;
              foreach (ListItem li in ddl.Items)
              {
                  if (li.Value == value)
                  {
                      found = true;
                  }
              }
          
              if (found)
              {
                  ddl.SelectedValue = value;
              } 
              else 
              {
                  // the value wasn't in the list,
                  // so if addItem is true, then add the value to the list and then set the value 
                  if (addItemIfNotFound)
                  {
                      ListItem li = new ListItem(text, value);
                      ddl.Items.Add(li);
                      ddl.SelectedValue = value;
                  }
                  else
                  {
                      // didn't find it and didn't add it
                      selected = false;
                  }
              }
              return selected;
          }
          

          【讨论】:

            猜你喜欢
            • 2011-08-07
            • 1970-01-01
            • 2011-08-18
            • 2013-11-15
            • 2014-01-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多