Member 13250972 Ответов: 1

Проблема с родительской страницей подписывающейся на вложенный дочерний элемент управления eventhandler


I am working on a budgeting project. I have listed incomes in a listview control with deductions nested in another listview control for each income listview item.
I am having trouble subscribing to the DeductionsChanged EventHandler. FOr the example below, I am trying to get the delete action to fire the DeductionsChanged event so that the BindIncome() can be called on the parent page; but DeductionsUpdated is always null, and ucDeductionsEditor_DeductionsUpdated never gets fired.

What am I missing here?

What I have tried:

USER CONTROL
<pre>namespace BillMoney.UserControls.BillMoneyUserControls
    {
        public partial class IncomeDeductionsEditor : BillMoney.App_Code.BaseUserControl
        {
            public EventHandler DeductionsUpdated;
            public virtual void OnDeductionsUpdated(EventArgs e)
            {
                DeductionsUpdated?.Invoke(this, e); // This is always null even though it is subscribed to in lvIncome_ItemDataBound 
            }

        public Int32 Invalue_IncomeId
        {
            get { return (ViewState["Invalue_IncomeId"] != null) ? (Int32)ViewState["Invalue_IncomeId"] : 0; }
            set
            {
                ViewState["Invalue_IncomeId"] = value;
                BindDeductions();
            }
        }
    
            ...
    
            protected void lvDeductions_ItemDeleting(object sender, ListViewDeleteEventArgs e)
            {
                ListView lvDeductions = (ListView)sender;
                Int32 deductionid = DataTypeMapper.GPC_CInt(lvDeductions.DataKeys[e.ItemIndex].Value);
                DeductionMGR.Delete(deductionid);
                OnDeductionsUpdated(null); // This DOES fire when I click the delete button
                BindDeductions();
            }
    
           ...
    
            private void BindDeductions()
            {
                List<DeductionDTO> deductions = new List<DeductionDTO>();
                deductions = DeductionMGR.GetList(Invalue_IncomeId);
                lvDeductions.DataSource = deductions;
                lvDeductions.DataBind();
            }
        }
    }

РАЗМЕТКА РОДИТЕЛЬСКОЙ СТРАНИЦЫ

<%@ Register Src="~/UserControls/BillMoneyUserControls/IncomeDeductionsEditor.ascx" TagName="DeductionsEditor" TagPrefix="UC" %>
<asp:ListView ID="lvIncome" DataKeyNames="IncomeId" runat="server" OnItemDataBound="lvIncome_ItemDataBound">
                <LayoutTemplate>
                    <div id="itemplaceholder" runat="server"></div>
                </LayoutTemplate>
                <ItemTemplate>
                    <div class="w3-row content-bubble">
                        <h3>
                            <asp:HyperLink ID="hlIncomeSource" Text="" NavigateUrl="#" Target="_blank" runat="server"></asp:HyperLink></h3>
                        <div class="row">
                            <div class="w3-col s3 l3 text-small text-bold">Start Date</div>
                            <div class="w3-col s3 l3 text-small text-bold">Pay Frequency</div>
                            <div class="w3-col s3 l3 text-small text-bold">Next Pay Date</div>
                            <div class="w3-col s3 l3 text-small text-bold w3-right-align">Income</div>
                        </div>
                        <div class="row">
                            <div class="w3-col s3 l3">
                                <asp:Label ID="lblStartDate" runat="server" CssClass="text-small"></asp:Label></div>
                            <div class="w3-col s3 l3">
                                <asp:Label ID="lblPayFrequency" runat="server" CssClass="text-small"></asp:Label></div>
                            <div class="w3-col s3 l3">
                                <asp:Label ID="lblNextPayDate" runat="server" CssClass="text-small"></asp:Label></div>
                            <div class="w3-col s3 l3 w3-right-align">
                                <asp:Label ID="lblGrossIncome" runat="server" CssClass="text-small"></asp:Label></div>
                        </div>
                        <div class="row w3-right-align">
                            <div class="w3-col l12 border-bottom">
                                <UC:DeductionsEditor ID="ucDeductionsEditor" OnDeductionsUpdated="ucDeductionsEditor_DeductionsUpdated" runat="server" />
                            </div>
                        </div>
                        <div class="row w3-right-align">
                            <div class="w3-col l12">
                                <asp:Label ID="lblTotalIncome" runat="server"></asp:Label>
                            </div>
                        </div>
                    </div>
                </ItemTemplate>
            </asp:ListView>


КОД РОДИТЕЛЬСКОЙ СТРАНИЦЫ ПОЗАДИ

namespace BillMoney.BillMoneyPages.Income
    {
        public partial class income_index : BillMoney.App_Code.BasePage
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                ...
    
                if (!Page.IsPostBack)
                {
    
                    BindIncome();
                }
            }
    
            private void BindIncome()
            {
                // Gross Income
                List<IncomeDTO> income_list = new List<IncomeDTO>();
                income_list = IncomeMGR.GetList(ActiveUser.UserId);
                lvIncome.DataSource = income_list;
                lvIncome.DataBind();   
            }
    		
    		...
    
            protected void lvIncome_ItemDataBound(object sender, ListViewItemEventArgs e)
            {
                if (e.Item.ItemType == ListViewItemType.DataItem)
                {
                    ListViewDataItem item = (ListViewDataItem)e.Item;
                    IncomeDTO income = (IncomeDTO)item.DataItem;
    
                    ...
    
                    IncomeDeductionsEditor ucDeductionsEditor = (IncomeDeductionsEditor)item.FindControl("ucDeductionsEditor");
                    ucDeductionsEditor.Invalue_IncomeId = income.IncomeId; // lvDeductions gets bound when Invalue_IncomeId is set
                    ucDeductionsEditor.DeductionsUpdated += ucDeductionsEditor_DeductionsUpdated;
                }
            }
    
            private void ucDeductionsEditor_DeductionsUpdated(object sender, EventArgs e)
            {
                BindIncome(); // This never fires when I click the Delete button on the USERCONTROL
            }
        }
    }

1 Ответов

Рейтинг:
8

Richard Deeming

ItemDataBound срабатывает только тогда, когда элемент привязывается к источнику данных. Это происходит только при начальной загрузке; когда вы нажимаете кнопку, чтобы отправить обратно на сервер, дерево элементов управления воссоздается без привязки данных, поэтому событие не срабатывает.

ItemCreated это было бы событие, которое можно было бы использовать для подключения обработчика событий, если бы вы по какой-то причине не могли сделать это через разметку. Но похоже, что вы уже подключили его в разметке, так что вам не нужно будет делать это снова в коде.

Я подозреваю, что проблема в том, что вы пропускаете event ключевое слово в коде элемента управления-behind:

public event EventHandler DeductionsUpdated;
событие - Справочник по C# | Microsoft Docs[^]

Возможно, вы захотите рассмотреть возможность использования Events свойство для хранения делегата, имитирующее определение других событий:
private static readonly object DeductionsUpdatedEvent = new object();

public EventHandler DeductionsUpdated
{
    add { Events.AddHandler(DeductionsUpdatedEvent, value); }
    remove { Events.RemoveHandler(DeductionsUpdatedEvent, value); }
}

protected virtual void OnDeductionsUpdated(EventArgs e)
{
    var handler = (EventHandler)Events[DeductionsUpdatedEvent];
    handler?.Invoke(this, e);
}
Как обрабатывать несколько событий с помощью свойств событий | Microsoft Docs[^]


Member 13250972

Ваши первые два абзаца ответили на него за меня. Мне нужно было подключить его во время мероприятия ItemCreated.


охраняемых недействительными lvIncome_ItemCreated(объект отправителя, ListViewItemEventArgs е)
{
если (электронная.Товар.ItemType == ListViewItemType.Элемента данных)
{
ListViewDataItem item = (ListViewDataItem)e.Предмет;
IncomeDeductionsEditor ucDeductionsEditor = (IncomeDeductionsEditor)элемент.FindControl("ucDeductionsEditor");
ucDeductionsEditor.DeductionsUpdated += ucDeductionsEditor_DeductionsUpdated;
}
}

Большое вам спасибо!!