我有一个ASCX用户控件,我正在尝试将其用于我的Web应用程序。
控件具有多个属性,需要设置才能使控件正常工作。
该控件用于GridView。控件的每个实例都需要来自其所在行的数据。
我尝试使用属性和Eval
方法设置属性值来分配值。例如:
网页代码:
<cm:TestManagerEditor runat="server" id="TestManagerEditor" FilePath='<%# System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath + "Some\\Path\\In\\The\\WebApp\\" + AccountYearPeriodOptionsGroupRandomTestManager.SelectedAccountValue + "\\" %>' />
我还尝试在RowDataBound
事件上设置值。例如:
网页代码:
private string PathToUserFiles = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath + "Some\\Path\\In\\The\\WebApp\\";
protected void GridViewData_RowDataBound(object sender, GridViewRowEventArgs e)
{
// this is the customized path to files for the selected account.
string UserFilePath = PathToUserFiles + AccountYearPeriodOptionsGroupRandomTestManager.SelectedAccountValue + "\\";
// set modal dialog properties and add the scripting to open those dialogs.
if (e.Row.RowType == DataControlRowType.DataRow)
{
Controls_Modals_TestManagerEditor EditorModal = e.Row.FindControl("TestManagerEditor") as Controls_Modals_TestManagerEditor;
EditorModal.FilePath = UserFilePath;
}
}
当我使用页面中的上述任一方法设置的属性访问控件时,值正确返回。但是,如果我试图从控件的代码隐藏中访问属性的值,它将返回属性的默认值(通常为NULL
或string.Empty
),而不是设置的值
例如,上面使用的FilePath
属性与其他任何属性一样声明:
UserControl代码:
/// <summary>
/// The path to the location of the uploaded files.
/// </summary>
private string _FilePath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath + "Some\\Path\\In\\The\\WebApp\\";
/// <summary>
/// Gets or sets the path to the location of uploaded files.
/// </summary>
public string FilePath
{
get
{
return _FilePath;
}
set
{
_FilePath = value;
}
}
但是当用户单击控件上的按钮以执行某些操作时,在UserControl的代码中访问时FilePath
的值为
System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath + "Some\\Path\\In\\The\\WebApp\\"
而不是预期的
System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath + "Some\\Path\\In\\The\\WebApp\\" + AccountYearPeriodOptionsGroupRandomTestManager.SelectedAccountValue
(基本上缺少字符串中的AccountYearPeriodOptionsGroupRandomTestManager.SelectedAccountValue
)。
奇怪的是,属性实际上将执行set
操作。其中一个肯定会执行操作,但然后迅速失去它的价值。 ModalTitle
属性将正确设置UX,但之后访问属性的值无法返回屏幕上显示的内容。
例如,以下设置访问者将在屏幕上正确设置TestManagerEditor_label
值,但无法设置_ModalTitle
的值:
UserControl代码:
/// <summary>
/// The text to display in the title of the Modal Dialog Box.
/// </summary>
private string _ModalTitle = "Test Manager";
/// <summary>
/// Gets or sets the text to display in the title of the Modal Dialog Box.
/// </summary>
public string ModalTitle
{
get
{
return _ModalTitle;
}
set
{
_ModalTitle = value;
TestManagerEditor_label.InnerText = value + " ";
TestManagerEditor_label.InnerHtml = TestManagerEditor_label.InnerHtml + "<span class=\"fa fa-pencil\"></span>";
}
}
有谁知道这里发生了什么以及为什么我的控件无法访问或保存其父页面设置的属性值?
答案 0 :(得分:0)
ASP.NET webforms的设计是&#34; state&#34;或者在呈现页面时将控件的值写入viewstate。这样,当您执行回发时,服务器代码可以回读这些值,并在回发之间保留它们。但是如果在代码中声明一个字符串,ASP.NET就不知道它需要保存和恢复该字符串。因此,在保存和恢复服务器控件的属性时,您的值会丢失。
正如ASP.NET为页面中的控件执行此操作一样,它也会对嵌套在UserControl中的服务器控件执行此操作。
一个真正简单的解决方法是在UserControl中包含一个像这样的控件:
<asp:hiddenfield id="filepath" runat="server">
然后使用它来存储您的值而不是字符串变量。假设为您的控件启用了viewstate,那么当您执行回发时,该字段的值将写入viewstate。它不会在回发之间迷失方向。
另一个想法 - 您是否希望用户能够通过查看页面源来查看您的服务器路径(某些\ path \ etc)?即使在视图状态下,它也只是编码,默认情况下不加密。 仅在控件中存储根据用户输入而不是整个路径更改的路径部分可能更好。您可以在需要时在服务器代码中检索路径的其余部分 - System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath
,而不是将其保存在viewstate中。
如果您不想在隐藏字段中存储值 - 假设有多个值或者它更复杂 - 您还可以执行以下操作:
你可以使用一个字符串,但我喜欢创建一个单独的类来存储我想要在回发之间保存的所有状态。这样,如果我需要保持另一个值,我不需要再次编写相同的代码来保存和重新加载多个值。
[Serializable]
public class ControlState
{
public string FilePath{get;set;}
}
然后在您的控制中执行此操作:
public partial class YourControl : System.Web.UI.UserControl
{
private ControlState _controlState;
public ControlState State { get { return _controlState; } }
protected void Page_Load(object source, EventArgs e)
{
_controlState= ViewState["controlState"] as ControlState ?? new ControlState();
}
protected void Page_PreRender(object sender, EventArgs e)
{
ViewState["controlState"] = _controlState;
}
然后,您可以通过State
属性读取和设置值。
PreRender
部分在呈现页面时将这些值保存到视图状态。
Page_Load
部分会从视图状态中读取这些值,以便您可以从代码中访问它们。