回发后自定义 DataControlField 不保留值
Custom DataControlField does not retain value after postback
我有问题。我创建了几个自定义 DataControlFields
,因为我需要在 DataGrid
.
上显示不是来自 DataSource
的数据
我设法获得了对 GridView
的控制,但我无法解决几个问题。
我的控件不会在回发之间保留它们的值。我将标记放在 UpdatePanel
中,我将其设置为 Conditional
。然后我配置了我的触发器,不包括 GridView
的触发器。我还尝试将 UpdateMode
设置为 Always
。我在这里得到相同的行为。
这是我的标记:
<asp:UpdatePanel UpdateMode="Conditional" ID="reportchooserUpdatePanel" runat="server">
<ContentTemplate>
<Triggers>
<asp:PostBackTrigger ControlID="ddlMonth" EventName="Load" />
<asp:PostBackTrigger ControlID="ddlMonth" EventName="SelectedIndexChanged" />
<asp:PostBackTrigger ControlID="ddlYear" EventName="DataBinding" />
<asp:PostBackTrigger ControlID="ddlYear" EventName="SelectedIndexChanged
<asp:PostBackTrigger ControlID="GenerateReportsButton" EventName="Click" />
</Triggers>
<table class="ms-formtable">
<tr>
<td class="ms-formlabel">
<asp:Label ID="MonthYearLabel" runat="server" Text=""></asp:Label>
</td>
<td class="ms-formbody align-right">
<asp:DropDownList OnSelectedIndexChanged="ddlMonth_SelectedIndexChanged" AutoPostBack="true" runat="server" ID="ddlMonth" OnLoad="ddlMonth_Load">
<asp:ListItem Value="1">Januar</asp:ListItem>
<asp:ListItem Value="2">Februar</asp:ListItem>
<asp:ListItem Value="3">März</asp:ListItem>
<asp:ListItem Value="4">April</asp:ListItem>
<asp:ListItem Value="5">Mai</asp:ListItem>
<asp:ListItem Value="6">Juni</asp:ListItem>
<asp:ListItem Value="7">Juli</asp:ListItem>
<asp:ListItem Value="8">August</asp:ListItem>
<asp:ListItem Value="9">September</asp:ListItem>
<asp:ListItem Value="10">Oktober</asp:ListItem>
<asp:ListItem Value="11">November</asp:ListItem>
<asp:ListItem Value="12">Dezember</asp:ListItem>
</asp:DropDownList>
</td>
<td class="ms-formbody align-right">
<asp:DropDownList OnSelectedIndexChanged="ddlYear_SelectedIndexChanged" AutoPostBack="true" OnDataBinding="ddlYear_DataBinding" ID="ddlYear" runat="server"></asp:DropDownList>
</td>
</tr>
<tr>
<td style="width:100%;" class="ms-formbody" colspan="3">
<asp:GridView AutoGenerateColumns="false" ShowHeaderWhenEmpty="true" CssClass="grid-view" Width="100%" ID="gvProjects" runat="server">
</asp:GridView>
</td>
<td></td>
<td></td>
</tr>
<tr>
<td class="ms-formtoolbar align-right" colspan="3">
<asp:HyperLink Target="_blank" Font-Size="X-Small" ID="hlGembox" NavigateUrl="http://www.gemboxsoftware.com/spreadsheet/free-version" runat="server"></asp:HyperLink>
<asp:Button OnClientClick="AddNotification('Please wait...')" ID="GenerateReportsButton" runat="server" Text="" OnClick="GenerateReportsButton_Click" />
</td>
<td></td>
<td></td>
</tr>
</table>
</ContentTemplate>
</asp:UpdatePanel>
这里是我的一个自定义代码 DataControlFields
。它们除了显示的控件外基本相同:
class TemplateDropDownControl : DataControlField
{
SPList reportslist = ListItemHelper.GetReportsList();
protected void InitializeDataCell(DataControlFieldCell cell, DataControlRowState rowState)
{
string ID = Guid.NewGuid().ToString();
DropDownList list = new DropDownList();
list.ID = ID;
FillContentTypeDropDown(list);
cell.Controls.Add(list);
}
public override void InitializeCell(DataControlFieldCell cell, DataControlCellType cellType, DataControlRowState rowState, int rowIndex)
{
//Call the base method.
base.InitializeCell(cell, cellType, rowState, rowIndex);
this.InitializeDataCell(cell, rowState);
}
protected override DataControlField CreateField()
{
return new BoundField();
}
public string DataField
{
get
{
object value = base.ViewState["DataField"];
if (value != null)
{
return value.ToString();
}
else
{
return string.Empty;
}
}
set
{
base.ViewState["DataField"] = value;
this.OnFieldChanged();
}
}
public override void ExtractValuesFromCell(System.Collections.Specialized.IOrderedDictionary dictionary, DataControlFieldCell cell, DataControlRowState rowState, bool includeReadOnly)
{
DropDownList list = cell.Controls[0] as DropDownList;
ListItem selectedValue = list.SelectedItem;
if (dictionary.Contains(DataField))
dictionary[DataField] = selectedValue.Value;
else
dictionary.Add(DataField, selectedValue.Value);
}
private void FillContentTypeDropDown(DropDownList ddlContentTypes)
{
if (reportslist == null)
return;
SPContentTypeCollection cts = reportslist.ContentTypes;
ddlContentTypes.Items.Clear();
foreach (SPContentType ct in cts)
{
ddlContentTypes.Items.Add(new ListItem() { Text = ct.Name, Value = ct.DocumentTemplateUrl + ct.DocumentTemplate.Replace("~site", "") });
}
}
}
最后,这是我将这些添加到我的页面的代码。我在标记中将 GridView
的 AutoGenerateColumns
属性 设置为 false:
private void BindDataGrid()
{
DataTable table = new DataTable();
table = new DataTable();
table.Columns.Add(ResourceHelper.LoadResource(ResourceName.ProjectnumberTableString));
table.Columns.Add(ResourceHelper.LoadResource(ResourceName.TemplateString));
table.Columns.Add(ResourceHelper.LoadResource(ResourceName.FileFormatString));
gvProjects.Columns.Clear();
gvProjects.DataSource = null;
//Fill DataTable here...
BoundField projectnumberField = new BoundField();
projectnumberField.HeaderText = ResourceHelper.LoadResource(ResourceName.ProjectnumberTableString);
projectnumberField.DataField = ResourceHelper.LoadResource(ResourceName.ProjectnumberTableString);
FileFormatCheckboxControl checkBoxControl = new FileFormatCheckboxControl();
checkBoxControl.DataField = ResourceHelper.LoadResource(ResourceName.FileFormatString);
checkBoxControl.HeaderText = ResourceHelper.LoadResource(ResourceName.FileFormatString);
TemplateDropDownControl dropDownControl = new TemplateDropDownControl();
dropDownControl.DataField = ResourceHelper.LoadResource(ResourceName.TemplateString);
dropDownControl.HeaderText = ResourceHelper.LoadResource(ResourceName.TemplateString);
gvProjects.Columns.Add(projectnumberField);
gvProjects.Columns.Add(dropDownControl);
gvProjects.Columns.Add(checkBoxControl);
gvProjects.DataSource = table;
gvProjects.DataBind();
}
有人知道我做错了什么吗?
编辑:也许我应该提到我在 Sharepoint 模式对话框中显示表单。
好吧,我用另一种方式解决了它,因为我不知道为什么我的问题一直发生。我现在只使用 asp:Table
并从代码隐藏生成整个内容。为此,我有一种方法可以在每个页面回发时调用。请务必注意仅从 Page_Load
调用此方法。当我从 Page_Init
.
调用它时它不起作用
这是我的代码:
private void BindDataGrid()
{
GenerateReportsButton.Enabled = true;
reportsTable.Rows.Clear();
TableHeaderRow headerrow = new TableHeaderRow();
TableHeaderCell pnumberheader = new TableHeaderCell();
TableHeaderCell templateheader = new TableHeaderCell();
TableHeaderCell fileFormatHeader = new TableHeaderCell();
pnumberheader.Text = ResourceHelper.LoadResource(ResourceName.ProjectnumberTableString);
templateheader.Text = ResourceHelper.LoadResource(ResourceName.TemplateString);
fileFormatHeader.Text = ResourceHelper.LoadResource(ResourceName.FileFormatString);
headerrow.Cells.Add(pnumberheader);
headerrow.Cells.Add(templateheader);
headerrow.Cells.Add(fileFormatHeader);
reportsTable.Rows.Add(headerrow);
if (ddlYear.SelectedItem == null || ddlMonth.SelectedItem == null)
{
int index = reportsTable.Rows.Add(new TableRow());
TableCell cell = new TableCell();
cell.ColumnSpan = 3;
cell.Text = ResourceHelper.LoadResource(ResourceName.NoListItemsForMonthYear);
reportsTable.Rows[index].Cells.Add(cell);
GenerateReportsButton.Enabled = false;
return;
}
//Get items here
if (items.Count == 0)
{
int index = reportsTable.Rows.Add(new TableRow());
TableCell cell = new TableCell();
cell.ColumnSpan = 3;
cell.Text = ResourceHelper.LoadResource(ResourceName.NoListItemsForMonthYear);
reportsTable.Rows[index].Cells.Add(cell);
GenerateReportsButton.Enabled = false;
return;
}
else
InsertRowIntoProjectTable("Intern", "Intern");
List<string> processedReports = new List<string>();
foreach(SPListItem item in items)
{
if (item[Variables.projectNumberField].ToString() != "Intern" && !processedReports.Contains(item[Variables.activityProject].ToString()))
{
InsertRowIntoProjectTable(item[Variables.activityProject].ToString(), item.ID.ToString());
processedReports.Add(item[Variables.activityProject].ToString());
}
}
}
那么你可以这样读取数据:
foreach(TableRow row in reportsTable.Rows)
{
//Important since foreach also iterates over headerrow
if (row.Cells[1].Controls.Count > 0 && row.Cells[1].Controls[0] is DropDownList)
{
string value1= row.Cells[0].Text;
string value2= ((DropDownList)row.Cells[1].Controls[0]).SelectedValue;
//do stuff with the data
}
}
如果有人仍然找到我上面的特定问题的答案,请随时添加。一旦确认有效,我会将其标记为已接受。
我有问题。我创建了几个自定义 DataControlFields
,因为我需要在 DataGrid
.
DataSource
的数据
我设法获得了对 GridView
的控制,但我无法解决几个问题。
我的控件不会在回发之间保留它们的值。我将标记放在 UpdatePanel
中,我将其设置为 Conditional
。然后我配置了我的触发器,不包括 GridView
的触发器。我还尝试将 UpdateMode
设置为 Always
。我在这里得到相同的行为。
这是我的标记:
<asp:UpdatePanel UpdateMode="Conditional" ID="reportchooserUpdatePanel" runat="server">
<ContentTemplate>
<Triggers>
<asp:PostBackTrigger ControlID="ddlMonth" EventName="Load" />
<asp:PostBackTrigger ControlID="ddlMonth" EventName="SelectedIndexChanged" />
<asp:PostBackTrigger ControlID="ddlYear" EventName="DataBinding" />
<asp:PostBackTrigger ControlID="ddlYear" EventName="SelectedIndexChanged
<asp:PostBackTrigger ControlID="GenerateReportsButton" EventName="Click" />
</Triggers>
<table class="ms-formtable">
<tr>
<td class="ms-formlabel">
<asp:Label ID="MonthYearLabel" runat="server" Text=""></asp:Label>
</td>
<td class="ms-formbody align-right">
<asp:DropDownList OnSelectedIndexChanged="ddlMonth_SelectedIndexChanged" AutoPostBack="true" runat="server" ID="ddlMonth" OnLoad="ddlMonth_Load">
<asp:ListItem Value="1">Januar</asp:ListItem>
<asp:ListItem Value="2">Februar</asp:ListItem>
<asp:ListItem Value="3">März</asp:ListItem>
<asp:ListItem Value="4">April</asp:ListItem>
<asp:ListItem Value="5">Mai</asp:ListItem>
<asp:ListItem Value="6">Juni</asp:ListItem>
<asp:ListItem Value="7">Juli</asp:ListItem>
<asp:ListItem Value="8">August</asp:ListItem>
<asp:ListItem Value="9">September</asp:ListItem>
<asp:ListItem Value="10">Oktober</asp:ListItem>
<asp:ListItem Value="11">November</asp:ListItem>
<asp:ListItem Value="12">Dezember</asp:ListItem>
</asp:DropDownList>
</td>
<td class="ms-formbody align-right">
<asp:DropDownList OnSelectedIndexChanged="ddlYear_SelectedIndexChanged" AutoPostBack="true" OnDataBinding="ddlYear_DataBinding" ID="ddlYear" runat="server"></asp:DropDownList>
</td>
</tr>
<tr>
<td style="width:100%;" class="ms-formbody" colspan="3">
<asp:GridView AutoGenerateColumns="false" ShowHeaderWhenEmpty="true" CssClass="grid-view" Width="100%" ID="gvProjects" runat="server">
</asp:GridView>
</td>
<td></td>
<td></td>
</tr>
<tr>
<td class="ms-formtoolbar align-right" colspan="3">
<asp:HyperLink Target="_blank" Font-Size="X-Small" ID="hlGembox" NavigateUrl="http://www.gemboxsoftware.com/spreadsheet/free-version" runat="server"></asp:HyperLink>
<asp:Button OnClientClick="AddNotification('Please wait...')" ID="GenerateReportsButton" runat="server" Text="" OnClick="GenerateReportsButton_Click" />
</td>
<td></td>
<td></td>
</tr>
</table>
</ContentTemplate>
</asp:UpdatePanel>
这里是我的一个自定义代码 DataControlFields
。它们除了显示的控件外基本相同:
class TemplateDropDownControl : DataControlField
{
SPList reportslist = ListItemHelper.GetReportsList();
protected void InitializeDataCell(DataControlFieldCell cell, DataControlRowState rowState)
{
string ID = Guid.NewGuid().ToString();
DropDownList list = new DropDownList();
list.ID = ID;
FillContentTypeDropDown(list);
cell.Controls.Add(list);
}
public override void InitializeCell(DataControlFieldCell cell, DataControlCellType cellType, DataControlRowState rowState, int rowIndex)
{
//Call the base method.
base.InitializeCell(cell, cellType, rowState, rowIndex);
this.InitializeDataCell(cell, rowState);
}
protected override DataControlField CreateField()
{
return new BoundField();
}
public string DataField
{
get
{
object value = base.ViewState["DataField"];
if (value != null)
{
return value.ToString();
}
else
{
return string.Empty;
}
}
set
{
base.ViewState["DataField"] = value;
this.OnFieldChanged();
}
}
public override void ExtractValuesFromCell(System.Collections.Specialized.IOrderedDictionary dictionary, DataControlFieldCell cell, DataControlRowState rowState, bool includeReadOnly)
{
DropDownList list = cell.Controls[0] as DropDownList;
ListItem selectedValue = list.SelectedItem;
if (dictionary.Contains(DataField))
dictionary[DataField] = selectedValue.Value;
else
dictionary.Add(DataField, selectedValue.Value);
}
private void FillContentTypeDropDown(DropDownList ddlContentTypes)
{
if (reportslist == null)
return;
SPContentTypeCollection cts = reportslist.ContentTypes;
ddlContentTypes.Items.Clear();
foreach (SPContentType ct in cts)
{
ddlContentTypes.Items.Add(new ListItem() { Text = ct.Name, Value = ct.DocumentTemplateUrl + ct.DocumentTemplate.Replace("~site", "") });
}
}
}
最后,这是我将这些添加到我的页面的代码。我在标记中将 GridView
的 AutoGenerateColumns
属性 设置为 false:
private void BindDataGrid()
{
DataTable table = new DataTable();
table = new DataTable();
table.Columns.Add(ResourceHelper.LoadResource(ResourceName.ProjectnumberTableString));
table.Columns.Add(ResourceHelper.LoadResource(ResourceName.TemplateString));
table.Columns.Add(ResourceHelper.LoadResource(ResourceName.FileFormatString));
gvProjects.Columns.Clear();
gvProjects.DataSource = null;
//Fill DataTable here...
BoundField projectnumberField = new BoundField();
projectnumberField.HeaderText = ResourceHelper.LoadResource(ResourceName.ProjectnumberTableString);
projectnumberField.DataField = ResourceHelper.LoadResource(ResourceName.ProjectnumberTableString);
FileFormatCheckboxControl checkBoxControl = new FileFormatCheckboxControl();
checkBoxControl.DataField = ResourceHelper.LoadResource(ResourceName.FileFormatString);
checkBoxControl.HeaderText = ResourceHelper.LoadResource(ResourceName.FileFormatString);
TemplateDropDownControl dropDownControl = new TemplateDropDownControl();
dropDownControl.DataField = ResourceHelper.LoadResource(ResourceName.TemplateString);
dropDownControl.HeaderText = ResourceHelper.LoadResource(ResourceName.TemplateString);
gvProjects.Columns.Add(projectnumberField);
gvProjects.Columns.Add(dropDownControl);
gvProjects.Columns.Add(checkBoxControl);
gvProjects.DataSource = table;
gvProjects.DataBind();
}
有人知道我做错了什么吗?
编辑:也许我应该提到我在 Sharepoint 模式对话框中显示表单。
好吧,我用另一种方式解决了它,因为我不知道为什么我的问题一直发生。我现在只使用 asp:Table
并从代码隐藏生成整个内容。为此,我有一种方法可以在每个页面回发时调用。请务必注意仅从 Page_Load
调用此方法。当我从 Page_Init
.
这是我的代码:
private void BindDataGrid()
{
GenerateReportsButton.Enabled = true;
reportsTable.Rows.Clear();
TableHeaderRow headerrow = new TableHeaderRow();
TableHeaderCell pnumberheader = new TableHeaderCell();
TableHeaderCell templateheader = new TableHeaderCell();
TableHeaderCell fileFormatHeader = new TableHeaderCell();
pnumberheader.Text = ResourceHelper.LoadResource(ResourceName.ProjectnumberTableString);
templateheader.Text = ResourceHelper.LoadResource(ResourceName.TemplateString);
fileFormatHeader.Text = ResourceHelper.LoadResource(ResourceName.FileFormatString);
headerrow.Cells.Add(pnumberheader);
headerrow.Cells.Add(templateheader);
headerrow.Cells.Add(fileFormatHeader);
reportsTable.Rows.Add(headerrow);
if (ddlYear.SelectedItem == null || ddlMonth.SelectedItem == null)
{
int index = reportsTable.Rows.Add(new TableRow());
TableCell cell = new TableCell();
cell.ColumnSpan = 3;
cell.Text = ResourceHelper.LoadResource(ResourceName.NoListItemsForMonthYear);
reportsTable.Rows[index].Cells.Add(cell);
GenerateReportsButton.Enabled = false;
return;
}
//Get items here
if (items.Count == 0)
{
int index = reportsTable.Rows.Add(new TableRow());
TableCell cell = new TableCell();
cell.ColumnSpan = 3;
cell.Text = ResourceHelper.LoadResource(ResourceName.NoListItemsForMonthYear);
reportsTable.Rows[index].Cells.Add(cell);
GenerateReportsButton.Enabled = false;
return;
}
else
InsertRowIntoProjectTable("Intern", "Intern");
List<string> processedReports = new List<string>();
foreach(SPListItem item in items)
{
if (item[Variables.projectNumberField].ToString() != "Intern" && !processedReports.Contains(item[Variables.activityProject].ToString()))
{
InsertRowIntoProjectTable(item[Variables.activityProject].ToString(), item.ID.ToString());
processedReports.Add(item[Variables.activityProject].ToString());
}
}
}
那么你可以这样读取数据:
foreach(TableRow row in reportsTable.Rows)
{
//Important since foreach also iterates over headerrow
if (row.Cells[1].Controls.Count > 0 && row.Cells[1].Controls[0] is DropDownList)
{
string value1= row.Cells[0].Text;
string value2= ((DropDownList)row.Cells[1].Controls[0]).SelectedValue;
//do stuff with the data
}
}
如果有人仍然找到我上面的特定问题的答案,请随时添加。一旦确认有效,我会将其标记为已接受。