我想从我的数据源中的一个属性驱动一个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
。我想依靠数据源控件来完成繁重的工作。
答案 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
之类的类似控件,但它们具有相同的局限性。
对于喜欢冒险的人们,还可以通过在控件中引入额外的DataSelectedField
和DataEnabledField
属性并将其顶部的Eval
作为原始数据绑定的一部分来完成这项工作算法(已经使用DataTextField
和DataValueField
来实现)。我觉得这对我的用例来说会涉及更多点,因此决定采用一个更简单的替代方法,但这绝对是一种有效的方法,甚至可以与我提出的解决方案一起使用,以实现更强大的RadioButtonList
。 / p>