1

概述

我有一个 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;
    }
}

问题

当我从控件所在的页面访问使用上述任一方法设置的属性时,值会正确返回。但是,如果我试图从控件的代码隐藏中访问属性的值,它会返回属性的默认值(通常是NULLor string.Empty)而不是设置的值。

例如,FilePath上面使用的属性的声明与其他任何属性一样:

用户控制代码:

/// <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;
    }
}

但是当用户点击控件上的一个按钮执行一些操作FilePath时,在UserControl的代码中访问时的值是

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,但之后访问该属性的值无法返回屏幕上显示的内容。

例如,以下 set 访问器将正确设置TestManagerEditor_label屏幕上的值,但无法设置 的值_ModalTitle

用户控制代码:

/// <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>";
    }
}

有谁知道这里发生了什么以及为什么我的控件无法访问或保存其父页面设置的属性值?

4

1 回答 1

0

ASP.NET webforms 的设计是在页面呈现时将控件的“状态”或值写入视图状态。这样,当您进行回发时,服务器代码可以读回这些值是什么,并在回发之间保留它们。但是如果您在代码中声明一个字符串,ASP.NET 不知道它需要保存和恢复该字符串。因此,当您的服务器控件的属性得到保存和恢复时,您的价值就会丢失。

正如 ASP.NET 对页面中的控件执行此操作一样,它也对嵌套在 UserControl 中的服务器控件执行此操作。

一个真正简单的解决方法是在 UserControl 中包含这样的控件:

<asp:hiddenfield id="filepath" runat="server">

然后使用它来存储您的值而不是字符串变量。假设为您的控件启用了视图状态,当您执行回发时,该字段的值将被写入视图状态。它不会在回发之间丢失。

另一个想法 - 您是否希望用户能够通过查看页面源来查看您的服务器路径(some\path\etc)?即使在视图状态中,它也只是编码,默认情况下不加密。最好将根据用户输入更改的路径部分存储在您的控件中,而不是整个路径。您可以在需要时在服务器代码中检索路径的其余部分,System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath而不是将其保存在视图状态中。

如果您不想将值存储在隐藏字段中 - 假设有多个值或更复杂 - 您也可以执行以下操作:

你可以只使用一个字符串,但我喜欢创建一个类来存储我想要在回发之间保存的所有状态。这样,如果我需要保留另一个值,我不需要再次编写相同的代码来保存和重新加载多个值。

[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部分从视图状态中读取这些值,以便可以从您的代码中访问它们。

于 2017-04-25T21:59:25.613 回答