Click here to Skip to main content
15,886,780 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
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();
            }
        }
    }

PARENT PAGE MARKUP

ASP.NET
<%@ 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>


PARENT PAGE CODE BEHIND

C#
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
            }
        }
    }
Posted
Updated 22-Jan-20 6:24am

1 solution

ItemDataBound is only fired when the item is being bound to the data source. That only happens on the initial load; when you click the button to post back to the server, the control tree is recreated without databinding, so the event won't fire.

ItemCreated would be the event to use to wire up the event handler, if you couldn't do it via the markup for some reason. But it looks like you've already wired it up in the markup, so you shouldn't need to do it again in the code-behind.

I suspect the problem is that you're missing the event keyword in the control's code-behind:
C#
public event EventHandler DeductionsUpdated;
event - C# Reference | Microsoft Docs[^]

You might want to consider using the Events property to store the delegate, to mimic how the other events are defined:
C#
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);
}
How to: Handle Multiple Events Using Event Properties | Microsoft Docs[^]
 
Share this answer
 
Comments
Member 13250972 22-Jan-20 22:33pm    
Your first two paragraphs answered it for me. I needed to wire it up during the ItemCreated event.


protected void lvIncome_ItemCreated(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
ListViewDataItem item = (ListViewDataItem)e.Item;
IncomeDeductionsEditor ucDeductionsEditor = (IncomeDeductionsEditor)item.FindControl("ucDeductionsEditor");
ucDeductionsEditor.DeductionsUpdated += ucDeductionsEditor_DeductionsUpdated;
}
}

Thank you so much!!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900