It seems like this should be straightforward but I'm boggling. I've got my listview all setup and bound to my LINQ datasource. The source is dependent on a dropdown list which decides which branch information to show in the listview. My edit template works fine but my insert template won't work because it wants the branch ID which I want to get from the dropdownlist outside the listview but I don't know how to both bind that value and set it in my template. It looks like this:
<InsertItemTemplate>
<tr style="">
<td>
<asp:Button ID="InsertButton" runat="server" CommandName="Insert"
Text="Insert" />
</td>
<td>
<asp:TextBox ID="RechargeRateTextBox" runat="server"
Text='<%# Bind("RechargeRate") %>' />
</td>
<td>
<asp:Calendar SelectedDate='<%# Bind("StartDate") %>' ID="Calendar1" runat="server"></asp:Calendar>
</td>
</tr>
</InsertItemTemplate>
I need to get a label in there that binds to the value of a databound asp dropdownlist outside of the listview so that the insert will work.
Use the OnSelectedIndexChanged (with AutoPostBack=True) callback for the DropDownList to manually set the values in the ListView to the defaults for that branch when the value of the DropDownList changes.
protected void BranchDropDownList_OnSelectedIndexChanged( object sender, EventArgs e )
{
DropDownList ddl = (DropDownList)sender;
RechargeRateTextBox.Text = BranchManager.GetRechargeRate( ddl.SelectedValue );
}
Wrap the whole thing up in an UpdatePanel and it can all happen via AJAX.
I ended up going with this, thanks twanfosson.
protected void ListView1_ItemInserting(object sender, System.Web.UI.WebControls.ListViewInsertEventArgs e)
{
e.Values["BranchID"] = DropDownList1.SelectedValue;
}
Related
How to find which control event got triggered, for example, if there are 5 columns in the repeater if the 2nd checkbox or 3rd drop-down list causes the event. How to find which control event got triggered, so that the particular control related logic alone will be executed without disturbing other column controls.
The sample repeater code is attached as follows,
<asp:Repeater ID="rptTest" runat="server">
<ItemTemplate>
<td class="repeater-col">
<div>
<asp:TextBox ID="txt1" runat="server"></asp:TextBox>
</div>
<div>
<asp:DropDownList ID="ddl1" runat="server" OnSelectedIndexChanged="ddl1_SelectedIndexChanged" AutoPostBack="true">
</asp:DropDownList>
</div>
<div>
<asp:CheckBox ID="chk1" runat="server" OnCheckedChanged="chk1_CheckedChanged" AutoPostBack="true" />
</div>
</td>
</ItemTemplate>
</asp:Repeater>
There are lot more dependent controls presented inside the repeater. Based on the selection of the controls the data to the other controls are bound and processed. The logic bounded to the repeater will be handled on the respective events for example on chk1_CheckedChanged and ddl1_SelectedIndexChanged
Kindly help on this! Thanks in advance!
You can cast the sender back to the correct Control type. Then you can access it's properties. If you want to know which items the control was in, you can use the NamingContainer
protected void ddl1_SelectedIndexChanged(object sender, EventArgs e)
{
DropDownList drp = sender as DropDownList;
drp.BackColor = Color.Green;
RepeaterItem item = drp.NamingContainer as RepeaterItem;
int itemIndex = item.ItemIndex;
}
I have a dynamically generated ListView which displays a set of groups, retrieved from a database. The ListView template looks like this:
<asp:ListView ID="lvGroups" runat="server">
<ItemTemplate>
<tr>
<td>
<asp:Label ID="lblGroupName" runat="server" Text='<%# Eval("GroupName") %>' />
</td>
<td>
<asp:LinkButton ID="lnkRemove" runat="server" Text="Remove" OnClick="lnkGroupRemove" OnClientClick="Confirm()" />
</td>
</tr>
</ItemTemplate>
</asp:ListView>
As you can see, there is a value, which is pulled from a database, and then a linkbutton for removing that value. When the linkbutton is clicked, it displays a javascript confirmation message, and if you click Yes on that message, then that specific entry will be removed from the database.
Unfortunately I cannot simply remove the GroupName where the ID = row number, because you can both add and remove groups, so that will quickly become inconsistent.
All I truly need is a way to retrieve the GroupName from the same row as the linkbutton that was clicked, if I can figure out how to do that, then I can easily configure a database query to successfully remove the entry. If you have another solution, however, that is also great.
I'm sad to say that I have no example code for the lnkGroupRemove event, as I simply have no clue where to start on this problem.
Any help on this subject would be much appreciated!
You can use the DataKeyNames attribute:
<asp:ListView ID="lvGroups" runat="server" DataKeyNames="ID,GroupName" >
and get the value this way in code-behind:
protected void lnkGroupRemove(object sender, EventArgs e)
{
ListViewItem item = (sender as LinkButton).NamingContainer as ListViewItem;
int ID = (int)lvGroups.DataKeys[item.DataItemIndex].Values["ID"];
string groupName = (string)lvGroups.DataKeys[item.DataItemIndex].Values["GroupName"];
}
I added an ID value to show that additional fields can be added to DataKeyNames and retrieved from code-behind, including fields that are in the data source but not displayed in the ListView.
I have a FormView that is used for viewing, editing and inserting items into a MSSQL database. The FormView is wired up to a LinqDataSource, and I use its Selecting event to filter the data displayed in the FormView based on parameters (columns) passed in the query string.
In the FormView I have a DropDownList that displays values from a related table. Everything works as it should except when I try to edit - for some reason, the selected value of the DropDownList is always empty when I try to save the edit (even when I have a value selected). The insert works as it should.
I have traced the problem down to my Selecting event where I do the filtering. If I comment out the method that does the filtering, it updates the item successfully - but I can't figure out why the filtering is breaking the update.
Here is my (shortened) FormView:
<asp:FormView ID="fvData" runat="server" AllowPaging="True"
DataKeyNames="ID" DataSourceID="ldsData"
ondatabound="fvData_DataBound">
<EditItemTemplate>
<table class="pad5">
<tr>
<td class="field-name">AREA:</td>
<td><asp:DropDownList ID="cboAREA" runat="server" DataTextField="AREA_NAME" DataValueField="AREA1" SelectedValue='<%# Bind("AREA") %>' DataSourceID="ldsAreas" /></td>
</tr>
<tr>
<td class="field-name">LOOP:</td>
<td><asp:TextBox ID="txtLOOP" runat="server" Text='<%# Bind("LOOP") %>' /></td>
</tr>
<tr>
<td class="field-name">LOOP DESCRIPTION:</td>
<td><asp:TextBox ID="txtLOOP_DESCRIPTION" runat="server"
Text='<%# Bind("LOOP_DESCRIPTION") %>' style="width: 600px" /></td>
</tr>
</table>
<asp:Button ID="btnUpdate" runat="server" Text="Update" CommandName="Update" CausesValidation="True" />
<asp:Button ID="btnCancel" runat="server" Text="Cancel" CommandName="Cancel" CausesValidation="False" />
</EditItemTemplate>
<InsertItemTemplate>
<table class="pad5">
<tr>
<td class="field-name">AREA:</td>
<td>
<asp:DropDownList ID="cboAREA" runat="server" DataTextField="AREA_NAME"
DataValueField="AREA1" SelectedValue='<%# Bind("AREA") %>' AppendDataBoundItems="true" DataSourceID="ldsAreas">
<asp:ListItem Text="" Value="" />
</asp:DropDownList>
</td>
</tr>
<tr>
<td class="field-name">LOOP:</td>
<td><asp:TextBox ID="txtLOOP" runat="server" Text='<%# Bind("LOOP") %>' /></td>
</tr>
<tr>
<td class="field-name">LOOP DESCRIPTION:</td>
<td><asp:TextBox ID="txtLOOP_DESCRIPTION" runat="server"
Text='<%# Bind("LOOP_DESCRIPTION") %>' style="width: 600px" /></td>
</tr>
</table>
<asp:Button ID="btnInsert" runat="server" Text="Insert" CommandName="Insert" CausesValidation="True" />
<asp:Button ID="btnCancel" runat="server" Text="Cancel" CommandName="Cancel" CausesValidation="False" />
</InsertItemTemplate>
</asp:FormView>
The LinqDataSource:
<asp:LinqDataSource ID="ldsData" runat="server"
ContextTypeName="E_and_I.EAndIDataDataContext" EnableDelete="True"
EnableInsert="True" EnableUpdate="True" EntityTypeName=""
TableName="INSTRUMENT_LOOP_DESCRIPTIONs" onselecting="ldsData_Selecting" OrderBy="ID ASC" >
</asp:LinqDataSource>
My ldsData_Selecting method:
protected void ldsData_Selecting(object sender, LinqDataSourceSelectEventArgs e)
{
EI.FilterData<INSTRUMENT_LOOP_DESCRIPTION>(ref e, db.INSTRUMENT_LOOP_DESCRIPTIONs, this.db);
}
And finally EI.FilterData:
public static void FilterData<T>(ref LinqDataSourceSelectEventArgs e, IEnumerable<T> source, EAndIDataDataContext db)
{
if (HttpContext.Current.Request.QueryString.Keys.Count > 0)
{
var result = source.AsQueryable();
bool filtered = false;
// get column names
var columnNames = db.Mapping.MappingSource.GetModel(typeof(EAndIDataDataContext)).GetMetaType(typeof(T)).DataMembers;
foreach (string key in HttpContext.Current.Request.QueryString.Keys)
{
string val = HttpContext.Current.Request.QueryString[key];
// check the query string key exists as a column in the table, etc
if (columnNames.SingleOrDefault(c => c.Name == key) != null && val.Trim() != "" && val != "*")
{
result = result.WhereLike(key, val.Replace("?", "_").Replace("*", "%"));
filtered = true;
}
}
if (filtered)
e.Result = result;
}
}
Is there any reason filtering the results would break the update (and ONLY the DropDownList's - textboxes work fine)? The filtering works perfectly (that is, the FormView only shows the records based parameters entered by the user); if you're wondering what the WhereLike extension method does, you can check out this question's answer.
Because when you post data with editing, you re bind your data and so you erase the selected Value.
Solution : Adjust your bind
If( ! IsPostBack)
{
//Here realize your bind of data
}
In order to persist your datas, use ViewState
With this solution When you post you don't re bind data, and so ViewState contains your selected value
There's a difference in the drop-down lists for your two cases, which I think is probably the cause of this. For Insert, you have AppendDataBoundItems="true", while for the Update form above it, this flag is not set (and it defaults to false). What that means in terms of the submitting form is that, for the Insert form, when it's rebinding it appends the items to the current list instead of clearing them; but for the Update form, because it's not set to append, it will clear the items and THEN binds them -- so the Binding is happening in both cases, but in the case of the Update form, it's clearing the items when that happens and giving you blank data.
Instead of just rejecting the filtering on Postback, which causes your form to fail eventually, I would instead filter based on the control that CAUSED the Postback. At the top of the function you can capture the control ID that caused the postback, and then you can filter only when it isn't a postback coming from the buttons that are triggering the data storage step. If that's in place, I believe you should be able to do away with the AppendDataBoundItems flags altogether.
A code snippet update of what I mean:
string initControl = Request.Form["__EVENTTARGET"];
if (!IsPostBack || (initControl != "btnInsert" && initControl != "btnUpdate") {
// code here
}
What this does is expand the check for PostBack so that the conditions are allowed EITHER if not a post back (which you tested previously), but critically, it'll also allow the lists to update if the form IS posted back, so long as the control posting back isn't one that is triggering an event dependent on the contents of those bound elements. That should mean that you avoid the problem of it only working for the first page load.
Additionally, if you need the control to bind regardless, you could add a global boolean variable to the script; set it to False by default, and then set it to True if the above condition is not met (i.e., if you're preventing the binding). Then you can check that boolean value in the Page_PreRender function, and if it's set to true, you can perform a late binding of the control at that step (which will only fire after the Insert/Update events have already processed, so any binding at that point will no longer affect the result of the form processing).
This is my repeater:
<asp:Repeater ID="myRepeater" OnItemCommand="myRepeater_ItemCommand" runat="server" OnItemDataBound="myRepeater_OnItemDataBound">
<HeaderTemplate>
<table width="99%" border="0" cellpadding="0" cellspacing="0">
<tr class="lgrey">
<td>Default</td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<table>
<tr>
<td>
<asp:LinkButton ID="lnk1" Text="Make Default" CommandName="SetDefault" runat="server" Visible="True" CommandArgument='<%#Eval("UserID") %>' CausesValidation="false"></asp:LinkButton>
<asp:Label ID="label1" Text="Yes" runat="server" Visible="False"></asp:Label>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
What I want is that when user clicks on any of
the "lnk1" link button in the list that repeater renders,
the link should be replaced with the label "label1"..
i.e. when the user clicks on "Make Default" link, it should be replaced with "Yes" label
Calling this method obj.SetDefaultAddress(); is setting the default address in the DB alright..
problem is with the display of the label1 and lnk1 when the repeater renders...
what is happening is that BOTH "Make Default" LinkButton and the "YES" label are getting displayed
under the "Default" column of the table inside my repeater.
I want some code that will check the "IsDefault" value in my DB and display "Make Default " link button
and "YES" label accordingly... i.e. if IsDefault's value in the DB is TRUE then "YES" should be displayed in the repeater
otherwise "Make Default"
Are you sure your piece of code in code behind under ItemCommand is executing?
I only changed the CommandName from SetDefault to SetDefaultAddress in aspx file to match with the one in code behind, it worked.
Where to start...
I think what's causing your problem is that the SelectedItem and the DefaultAddress are not mapped to each other, so when you click the button you're getting the selected index set and the OnItemDatabound event is showing/hiding what you want, but when the grid is initialized from the database, the SelectedItem is not being set.
I don't know what your datasource is, and there's obviously more code to this than what you've posted, but if you can look at the e.Item.DataItem in the myRepeater_ItemDataBound handler, you can set the current item as selected when the address is the default (e.Item.ItemType... or use your "selectedIndex" counter)
I will probably do it from markup itself - this is assuming that you have "IsDefault" column/property of bit/boolean type in your data-source indicating the address is default. So use following markup:
...
<tr>
<td>
<asp:LinkButton ID="lnk1" Text="Make Default" CommandName="SetDefault" runat="server" Visible='<%# !Eval("IsDefault") %>' CommandArgument='<%#Eval("UserID") %>' CausesValidation="false"></asp:LinkButton>
<asp:Label ID="label1" Text="Yes" runat="server" Visible='<%# !Eval("IsDefault") %>'></asp:Label>
</td>
</tr>
...
You need to control visibility based on property in your data source (either using markup or ItemDataBound event). Also when SetDefault link is clicked, you must either re-bind the repeater new state or toggle visibility explicitly (as your current code is doing).
EDIT:
If data binding expression are not working then you have to do it in ItemDataBound event. I see that you have already tried that but there is one mistake - bllUsers obj=new bllUsers(); will always have IsDefault as false - you need to use data item. For example,
protected void myRepeater_ItemDataBound(Object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
bllUsers obj = e.Item.DataItem as bllUsers;
((Label)e.Item.FindControl("ldefault")).Visible = obj.isDefault;
((Button)e.Item.FindControl("btnMakeDefault")).Visible = ! obj.isDefault;
}
}
I'm missing something here...
I need to access the values of the controls on the item that is leaving editmode, thus firing ItemUpdating.
I found how to get the key value so I know which record in the database I have to update. The problem is that I can't seem to access the values of the controls on the editing row.
the EditTemplate contains a few checkboxes, a dropdown and textbox. I need to access these values so I can update the record.
When looking at the eventargs, nothing shows.
I think I'm overlooking something crucial here, any help would be handy.
You can also use "ListView.EditItem.FindControl("X")" to access control directly.
Protected Sub ListView_ItemUpdating(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ListViewUpdateEventArgs) Handles ListView.ItemUpdating
Dim DropDownListddl As DropDownList = ListView.EditItem.FindControl("DropDownListddl")
Lblwarning.Text = DropDownListddl.SelectedValue
End Sub
There are two ways I can think to do this.
The first way would be to use a datasource that supports an update command and using two way binding to up date the values. The following snipped uses two way binding to populate the name and student fields and it will also update them for you.
<EditItemTemplate>
<tr style="background-color: #FFCC66;color: #000080;">
<td>
<asp:Button ID="UpdateButton" runat="server" CommandName="Update"
Text="Update" />
<asp:Button ID="CancelButton" runat="server" CommandName="Cancel"
Text="Cancel" />
</td>
<td>
<asp:TextBox ID="nameTextBox" runat="server" Text='<%# Bind("name") %>' />
</td>
<td>
<asp:TextBox ID="studentTextBox" runat="server" Text='<%# Bind("student") %>' />
</td>
</tr>
</EditItemTemplate>
If you are not using a datasource that supports this you can do one other thing.
Notice how the update button has a command called "Update". You can use this to fetch the control values you want by handling the list views ItemCommand Event.
protected void ListView1_ItemCommand(object sender, ListViewCommandEventArgs e)
{
if (e.CommandName == "Update")
{
TextBox box = (TextBox)e.Item.FindControl("nameTextBox");
string name = box.Text;
}
}
You can find any control in the editied item by simply calling find control and passing it the control's ID, and don't forget the cast.
Hope this helps