【问题标题】:How do I declaratively bind 'SelectedValue' to datasource field?如何以声明方式将“SelectedValue”绑定到数据源字段?
【发布时间】:2018-12-02 06:54:10
【问题描述】:

我想从我的数据源中的一个属性中驱动一个 RadioButtonLists SelectedValue 属性,但我无法让它工作。

我的页面上有一个<asp:RadioButtonList,绑定到<asp:ObjectDataSource。该数据源又提供以下模型类:

public class CollectionWithDefault : Collection<string>
{
    CollectionWithDefault(IEnumerable<string> items, string defaultItem)
    {
        foreach (var item in items)
            Add(item);

        DefaultItem = defaultItem;
    }

    public string DefaultItem { get; }
}

请注意,这个类是一个标准的字符串集合,它还公开了其中哪一个是默认选项。

考虑一下我有以下价值提供者的实现。这是一个简单的内存实现,但请记住,这可能来自数据库或任何其他来源:

public static class ItemProvider
{
    public static CollectionWithDefault GetAvailableItems()
    {
        var items = new [] { "option1", "option2", "option3" };

        return new CollectionWithDefault(items, items[1]);
    }
}

我尝试了以下方法:

<asp:ObjectDataSource runat="server"
    ID="ItemSource"
    TypeName="MyNamespace.ItemProvider"
    SelectMethod="GetAvailableItems" />
<asp:RadioButtonList runat="server" 
    DataSourceID="ItemSource"
    SelectedValue='<%# Eval("DefaultItem") #>' />

我在Eval 调用中遇到以下异常:

System.InvalidOperationException: 'Eval()、XPath() 和 Bind() 等数据绑定方法只能在数据绑定控件的上下文中使用。'

如何确保根据来自我的数据源的字段预先选择正确的收音机?

更改集合模型本身以使其工作是可以接受的,但我无法从代码隐藏中设置SelectedValue。我想依靠数据源控件来完成繁重的工作。

【问题讨论】:

  • 很确定您必须使用后面的代码来设置选定的索引或选定的值。 SelectedValue 不是 asp:RadioButtonList 控件的有效属性。
  • @wazz SelectedValue 绝对有效,只是在智能感知中不显示。
  • 我收到一个错误:The 'SelectedValue' property cannot be set declaratively.
  • 你能分享一段你看到这个@wazz的代码吗?我以前从未见过此错误消息,我只是仔细检查了我的真实生产代码,我可以向您保证 RadioButtonList 有一个 SelectedValue 并且您应该能够以声明方式设置它。
  • @wazz,仅供参考,我找到了解决方法并添加为答案。

标签: asp.net data-binding webforms


【解决方案1】:

通过扩展原始 RadioButtonList 控件并修改核心数据绑定方法以支持 ListItem 对象,我设法无缝地完成这项工作,而无需在代码隐藏中手动分配。

它是这样的:

public class MyRadioButtonList : RadioButtonList
{
    protected override void PerformDataBinding(IEnumerable dataSource)
    {
        if (dataSource is IEnumerable<ListItem> listItems)
        {
            ...

            foreach (var listItem in listItems)
                Items.Add(listItem);

            ...
        }
        else
        {
            base.PerformDataBinding(dataSource);
        }
    }    
}

有了这个,只需将我的源模型转换为表示层上的IEnumerable&lt;ListItem&gt;(通过适配器/代理实现很容易完成),然后将这些ListItems 提供给控件。

一旦我得到这个,我可以看到我选择的项目根据数据源字段正确反映在 UI 中。考虑到扩展是多么微不足道,我觉得这很值得:)

相同的继承方法可能可用于类似的控件,例如CheckBoxList,它具有相同的限制。

对于更喜欢冒险的人,也可以通过在控件中引入额外的 DataSelectedFieldDataEnabledField 属性并在它们之上使用 Eval 作为原始数据绑定算法的一部分来完成这项工作(已经这样做了) DataTextFieldDataValueField)。我觉得这对我的用例会涉及更多,因此决定使用更简单的覆盖,但这绝对是一种有效的方法,甚至可以沿用我提出的解决方案,以获得更强大的RadioButtonList

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-23
    • 2013-12-25
    • 1970-01-01
    相关资源
    最近更新 更多