在自定义组件中一次只允许一个可编辑字段

时间:2019-03-21 00:09:13

标签: c# asp.net webforms

我正在使用Web表单,并且具有一系列遵循相同模式的输入字段。他们有一个标签来显示文本,只需单击一个按钮即可切换到文本字段,从而保存文本。

我只希望用户一次编辑一个字段,这样,如果他们开始编辑第二个字段,则第一个字段将被保存。

我的代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace vk_HVK_Web.User_Controls
{
    [ValidationProperty("Text")]
    [ToolboxData("<{0}:EditableLabel runat=server></{0}:EditableLabel>")]
    public partial class EditableLabel : System.Web.UI.UserControl
    {
        public event EventHandler OnSave;
        public static EditableLabel CurrentEditing;
        public string DisplayText { get
            {
                return this.Text.ToUpper();
            }
        }
        public string Text { get => txtInput.Text; set => txtInput.Text = value; }

        public bool Editable { get => txtInput.Visible; set => txtInput.Visible = value; }

        protected void Page_PreRender(object sender, EventArgs e)
        {
            if (Editable)
            {
                txtInput.Visible = true;
                lblText.Visible = false;
                btnEditSave.CssClass = "fas fa-save";
                sectionEditable.CssClass = "col";
            }
            else
            {
                lblText.Visible = true;
                txtInput.Visible = false;
                btnEditSave.CssClass = "fas fa-pencil-alt";
                sectionEditable.CssClass = "col col-form-label text-left";
            }
            lblText.Text = DisplayText;
        }
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void txtInput_TextChanged(object sender, EventArgs e)
        {
            this.Text = txtInput.Text;
        }

        protected void btnEditSave_Click(object sender, EventArgs e)
        {
            if (Editable)
            {
                Save();
            } else
            {
                Edit();
            }

        }

        public void Edit()
        {
            if (CurrentEditing != null && CurrentEditing != this && CurrentEditing.Editable)
                CurrentEditing.Save();
            CurrentEditing = this;
            Editable = true;
        }
        public void Save()
        {
            Editable = false;
            if (OnSave != null)
                OnSave(this, EventArgs.Empty);
        }
    }
}

我不认为设计中的代码很有用,但无论如何这里都是这样:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="EditableLabel.ascx.cs" Inherits="vk_HVK_Web.User_Controls.EditableLabel" %>
<div class="row">
                    <div class="col-12">
                        <div class="row">
                            <div class="col-4 col-form-label text-right">Start Date: </div>
                            <asp:Panel runat="server" id="sectionEditable">
                                <asp:Label ID="lblText" runat="server" Text="" ></asp:Label>
                                <asp:TextBox Visible="false" ID="txtInput" runat="server" Text="" OnTextChanged="txtInput_TextChanged" CssClass="form-control" ></asp:TextBox>
                            </asp:Panel>
                            <div class="col-4 col-form-label">
                                <span><asp:LinkButton ID="btnEditSave" runat="server" OnClick="btnEditSave_Click" /></span>
      </div>

    </div>
  </div>
</div>

如您所见,当他们单击按钮进行编辑时,它要做的第一件事是检查是否正在编辑其他内容,如果要保存,则进行保存。 save方法会更改组件的状态,并使其不再可编辑。

就目前而言,单独进行切换非常有效,但是调用静态变量的Save()方法似乎根本不会影响其状态。

我们将不胜感激。我是Webforms的新手,所以如果我做错状态管理,请告诉我如何正确执行。谢谢。

1 个答案:

答案 0 :(得分:0)

好的,这花了我2天的时间,但是我知道对ASP.NET有很多了解。

我的解决方案是2倍,首先是由于某种原因,我认为静态生存期是针对每个用户的,就像在前端框架中那样,并非如此。这意味着它已在所有用​​户和所有页面之间共享。不好吧?

由于我想每页使用它,因此我使用了ViewState。用户控件有自己的ViewState,我需要Page,但是它是protected,因此无法使用。

我使用以下扩展程序类公开了ViewState

    public static class SharedViewStateExtension
    {
        public static StateBag GetProtectedViewState(this Page page)
        {
            var viewStateField = typeof(Page).GetProperty("ViewState", BindingFlags.NonPublic | BindingFlags.Instance);
            return (StateBag) viewStateField.GetValue(page);
        }
    }

当然,无论您放入ViewState中的任何内容都必须可序列化,而我无法做到这一点。因此,我将EditableLabels存储在会话级词典中,其中的键是保存在ViewState中的GUID。

第二个问题是ControlFromPriviousPageLoad != ControlFromNextPageLoad。每次页面加载都会生成新组件。取而代之的是,我还是比较每个页面应该唯一的ID。

我知道所有这些听起来很讨厌,但是ASP.NET令人作呕,所以就让我们离开吧。

结果类:https://paste.rs/9bU.cs