我正在尝试创建ASP.NET服务器控件(纯代码,没有ascx模板 - 因为控件必须完全包含在.dll中,并且它不能依赖于外部.ascx文件),并且我在动态添加时遇到问题转发的项目。
我想将项目添加到转发器以响应SelectedIndexChanged事件,但是当我在该事件中执行第二个DataBind()时,我将丢失ViewModel中的数据(例如,文本框包含默认数据而不是用户输入的文本)。 / p>
我的代码的简化版本(大部分借用了MS复合控件示例 - http://msdn.microsoft.com/en-us/library/3257x3ea%28v=vs.100%29.aspx):
[ToolboxData("<{0}:FilterControl runat=server />")]
public class FilterControl : CompositeControl, IPostBackDataHandler
{
private List<FilteringProperty> elements = new List<FilteringProperty>();
private DropDownList filteringElementsDropDownList;
private Repeater usedFiltersRepeater;
[Bindable(true), DefaultValue(null), Description("Active filters")]
public List<FilteringProperty> UsedElements
{
get
{
EnsureChildControls();
if (ViewState["UsedElements"] == null)
{
ViewState["UsedElements"] = new List<FilteringProperty>();
}
return (List<FilteringProperty>)ViewState["UsedElements"];
}
set
{
EnsureChildControls();
ViewState["UsedElements"] = value;
}
}
protected override void RecreateChildControls()
{
EnsureChildControls();
}
protected override void CreateChildControls()
{
Controls.Clear();
filteringElementsDropDownList = new DropDownList { AutoPostBack = true };
usedFiltersRepeater = new Repeater();
foreach (var element in elements)
{
filteringElementsDropDownList.Items.Add(new ListItem(element.DisplayName));
}
filteringElementsDropDownList.SelectedIndexChanged += (sender, e) =>
{
string selectedText = filteringElementsDropDownList.SelectedValue;
FilteringProperty condition = elements.First(x => x.DisplayName == selectedText);
var toRemove = filteringElementsDropDownList.Items.Cast<ListItem>().FirstOrDefault(x => x.Text == condition.DisplayName);
if (toRemove != null)
{
filteringElementsDropDownList.Items.Remove(toRemove);
}
UsedElements.Add(condition);
// ======> A <========
};
usedFiltersRepeater.ItemDataBound += (sender, args) =>
{
FilteringProperty dataItem = (FilteringProperty)args.Item.DataItem;
Control template = args.Item.Controls[0];
TextBox control = (TextBox)template.FindControl("conditionControl");
control.Text = dataItem.DisplayName;
// ======> C <========
};
usedFiltersRepeater.ItemTemplate = // item template
usedFiltersRepeater.DataSource = UsedElements;
usedFiltersRepeater.DataBind();
// ======> B <========
Controls.Add(filteringElementsDropDownList);
Controls.Add(usedFiltersRepeater);
}
}
我用(A),(B)和(C)
标记了代码的重要部分问题是,(A)在DataBinding(B和C)之后执行,因此在下一次回发之前,UsedElements中的更改不可见。
可以在(A)之后添加usedFiltersRepeater.DataBind();
,但是重新创建所有控件而没有来自viewstate的数据(即空)
有没有办法在数据绑定后动态更改转发器,以便保留包含控件的数据?
Tl; dr - 我有一个DropDownList,我想在SelectedIndexChanged上向Repeater添加可编辑的项目(不会丢失viewstate)。
答案 0 :(得分:0)
我终于解决了我的问题。 我的解决方案相当脏,但似乎工作正常。
而不是简单的数据绑定:
例如:
FilterState state = GetState();
state.Conditions.Add(new ConditionState { Item = condition });
SetState(state);