如何以声明方式将“ SelectedValue”绑定到数据源字段?

时间:2018-06-22 18:44:57

标签: asp.net data-binding webforms

我想从我的数据源中的一个属性驱动一个RadioButtonList s 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。我想依靠数据源控件来完成繁重的工作。

1 个答案:

答案 0 :(得分: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<ListItem>(使用适配器/代理实现即可轻松完成),然后提供这些ListItem到控件。

一旦完成此操作,就可以基于数据源字段看到选择的项目正确反映在UI中。考虑到扩展的琐碎性,我觉得很值得:)

相同的继承方法可能可以用于类似CheckBoxList之类的类似控件,但它们具有相同的局限性。

对于喜欢冒险的人们,还可以通过在控件中引入额外的DataSelectedFieldDataEnabledField属性并将其顶部的Eval作为原始数据绑定的一部分来完成这项工作算法(已经使用DataTextFieldDataValueField来实现)。我觉得这对我的用例来说会涉及更多点,因此决定采用一个更简单的替代方法,但这绝对是一种有效的方法,甚至可以与我提出的解决方案一起使用,以实现更强大的RadioButtonList。 / p>