I have a dropdownlist where I need to store more data than the standard list item allows. The approach I've taken is to add an attribute to each of the listitems.
I monitor for changes and can return the SelectedIndex, but I'm not sure how to get the attribute back from there, or whether there are any easier ways of achieving this.
Any ideas?
Try this:
ddl.SelectedItem.Attributes["key"];
I did try this once before and i figured i could not really use the attribute's on the DropDownList attributes.
What i did was the following:
Create a list containing a KeyValuePair. The Key in the KeyValuePair is the same ID as you put in your DropDownList Item.
The value of the KeyValuePair, is the value (or values) that you would like to keep/connect with your item.
You can store the List in your viewState and read the data once you have selected an item in your DropDownList and find the right KeyValuePair using the ID.
So you can "store" the data like this:
var listKeyValuePair = new List<KeyValuePair<int, string>>();
listKeyValuePair.Add(new KeyValuePair<int, string>(1, "data"));
ViewState["DataList"] = listKeyValuePair;
And you can get your data like this:
var listKeyValuePair = (List<KeyValuePair<int, string>>)ViewState["DataList"];
var dataILikeToHave = listKeyValuePair.Find(k => k.Key == Convert.ToInt16(dropDownlist.SelectedItem.Value));
Hi
In ASPxGridView, is there a way to get a row by its VisibleIndex or KeyValue so that I can change any column value in it?, I mean something like this:
var row = myGrid.SelectRowByKeyValue(myKeyValue);
OR:
var row = myGrid.SelectRowByVisibleIndex(myKeyValue);
row["Column1"] = true;
Edit:
What I'm tring to do is that every time I hit the button I want to check one specific row (I'm using ajax to not reload all the page);
Thanks
This can be done using the ASPxGridView.GetRow() method. NOTE, that changing the value in the DataRow is not enough. If you want these changes to be preserved, save them to the DB.
Since you are using unbound columns, you should handle the CustomUnboundColumnData event and provide modified data for this row within this event handler. The common approach is described in the Providing Data for Unbound Columns topic. If this does not help, please describe in greater details.
UPDATE
Your approach is incorrect. The ASPxGridView does not provide a method to set a text of a certain cell (TD). Instead, you should force the grid to raise the CustomUnboundColumnData event. This can be done using the ASPxGridView's DataBind method. In this event handler, you should determine the KeyField value of the processed row, compare it with the keyField value of the row where the button was clicked and return the required value. This is how I would implement this feature...
I solved it by using this code:
for (int i = 0; i < myGridView.VisibleRowCount; i++)
{
if ( [My condition] )
{
(
(CheckBox)myGridView
.FindRowCellTemplateControl(i,
myGridView.Columns["MyColumnName"] as GridViewDataColumn,
"My_Unbound_Control_Name"
)
).Checked = true;
}
}
I's may not be the right way to do it but I couldn't solve it another way.
NOTE: i havent implement the above solution but closing this question and accepting this as answer even thou i havent implement.
what is the best way of doing? and i know that i can store the repeater in a different var and compare but i just wanted to know the elegant way of doing.
here is my for loop code that i want to compare and update the values that have changed and ignore the values that have not changed
GridViewRow row = gv.SelectedRow;
Repeater _rpt = gv.Rows[e.RowIndex].Cells[8].FindControl("rptReg") as Repeater;
Repeater _rpt1 = gv.Rows[e.RowIndex].Cells[9].FindControl("rptVisitor") as Repeater;
for (int i = 0; i < _rpt.Items.Count; i++) {
TextBox _txt = _rpt.Items[i].FindControl("txtId") as TextBox;
TextBox _txt1 = _rpt.Items[i].FindControl("txtName") as TextBox;
if (_rpt1.Items.Count > i)
TextBox _txt3 = _rpt1.Items[i].FindControl("txtVisitor") as TextBox;
//update db
}
}
It's a total hack and I'm sure there is a more elegant way to handle it but you could throw a hidden field in there and set up your form elements with an onchange script to update the value of the hidden field. Then just check for the value of the hidden field.
Hopefully someone has a better way to do it than that but if all else fails.
If you add a class to the hidden field of "hiddenIndicator" and to your form elements of "causesChanged" then the following Jquery should do what you want:
$(document).ready(function() {
$('input.causesChanged').change(function() {
$(this)
.closest('tr') // get the parent row
.find("input.hiddenIndicator") // find children that match the selector
.val('1'); //the value that indicates a change occured
});
})
I haven't tested that code but I used something similar in a project once.
I write an imagebutton to a table cell in a new row when a user selects an item in a list:
ImageButton imgbtnRemove = new ImageButton();
imgbtnRemove.ID = "uxStandardLetterDeleteImage_" + items.letterName;
imgbtnRemove.CommandName = "uxStandardLetterDeleteImage_" + items.letterName;
imgbtnRemove.ImageUrl = items.remove;
imgStatus.AlternateText = "Remove";
tRow.Cells[3].Controls.Add(imgbtnRemove);
When the new imagebutton is clicked, I can't seem to get a handle to it. I see it in Page_PreRender event, where I also reload the table on each postback.
string returnData = Request.Form.ToString();
but iterating through the form controls images:
if (c is System.Web.UI.WebControls.Button ||
c is System.Web.UI.WebControls.ImageButton)
does not find it. I can find it if I manually put in a:
imgbtnRemove.Click += new System.Web.UI.ImageClickEventHandler(this.ButtonClick);
in the Page_Load and then grab it in the click event:
switch (((System.Web.UI.WebControls.ImageButton)sender).CommandName)
...
but because there are new rows being added and deleted, this gets rather ugly programmatically. I'm thinking there must be an elegant solution to dynamic imagebutton creation and retrieval on the fly from server side code. I've done a lot of digging but this one is stumping me.
Thanks in advance...
If you're creating dynamic controls during the event handling phase of the Page lifecycle (for example, in the item selected event), then the control will be gone on the next postback.
In order for dynamic controls to be registered with ViewState, they have to be created in the Init phase of the event lifecycle.
Also, you say you're iterating through the Form's controls... when you are adding the imagebutton to the table's cells. Are you recursively descending the control heirarchy to look for the imagebutton?
i've populated a dropdownlist control with different text properties but each text properties had THE SAME value (text property was A, value properties is blah,text property was B, value properties is blahblah, etc... )
ASP.net only checks value properties on postback and because ALL values were the same (for
testing reason) this little annoying behavior happened. Is there a work around? does this mean you can't never have the value to be the same?
Sounds like you are working on the wrong event. Try SelectedIndexChanged.
Ensure you also have the AutoPostBack property set to True.
Resolved
OK, so I got digging on this since I was curious :)
There is a "problem" when databinding with non-unique values.
So, firstly, I publicly apologise for saying otherwise.
To replicate:
ASPX
<asp:DropDownList ID="myDDL" runat="server" AutoPostBack="True">
</asp:DropDownList>
<asp:Label ID="lblSelItem" runat="server"Text="Currently Selected Item: 0"></asp:Label>
<asp:Label ID="lblSelVal" runat="server" Text="Currently Selected Value: X"></asp:Label>
Code-Behind
List<string> MyData()
{
List<string> rtn = new List<string>();
rtn.Add("I am the same value!");
rtn.Add("I am the same value!");
rtn.Add("I am the same value!");
rtn.Add("I am the same value!2");
return rtn;
}
protected void Page_Init()
{
if (!Page.IsPostBack)
{
// Load the Data for the DDL.
myDDL.DataSource = MyData();
myDDL.DataBind();
}
}
protected void Page_Load(object sender, EventArgs e)
{
// Display the Currently Selected Item/Value.
lblSelItem.Text = "Currently Selected Item: " + myDDL.SelectedIndex.ToString();
lblSelVal.Text = "Currently Selected Value: " + myDDL.SelectedValue;
}
Run, changing the values in the DropDownList. Note that a PostBack does not occur.
When looking at the Source, I realised that we need to explicitly set the "value" attribute for the <option> elements generated by the server control, which lead me to do something like:
New Code-Behind
Dictionary<string, string> MyTwoColData()
{
Dictionary<string, string> rtn = new Dictionary<string, string>();
rtn.Add("1", "I am the same value!");
rtn.Add("2", "I am the same value!");
rtn.Add("3", "I am the same value!");
return rtn;
}
protected void Page_Init()
{
if (!Page.IsPostBack)
{
// Load the Data for the DDL.
Dictionary<string, string> data = MyTwoColData();
foreach (KeyValuePair<string, string> pair in MyTwoColData())
{
myDDL.Items.Add(new ListItem(pair.Value, pair.Key));
}
myDDL.DataBind();
}
}
This explcitly sets the values to the "1", "2", "3" etc making them unique, while still displaying the correct data within the list.
Obviously, you can change this to work with single-column lists but just running through a for loop and using the value of i or something.
As to good workarounds with DataSets, not sure.
Realistically, would we present a list of options with the exact same values to the user?
I personally think not, which is probably why this "problem" hasn't been addressed :)
Enjoy!
PS:
Oh, I should also add, if you want to use the text value in the "fix" then change it to SelectedItem rather than SelectedValue.
ASP.NET can't distinguish between different items with the same values in the dropdown because when the browser sends the HTTP POST, it sends just the selected value.
ASP.NET will find the FIRST item in the dropdown with a value that matches.
You need to ensure that each item in the dropdown has a distinct value. You could do this by adding a key to each value. In other words, instead of having "blah" for each value, you'd use "blah-1", "blah-2", etc.
The problem is that if the selected index doesn't change the postback won't fire. In the case where the user makes the same selection, the selected index does not change.
Sorry that this doesn't answer the question, but it does explain the behavior as far as I know.
The SelectedIndexChanged won't even trigger because all the listitem value in the dropdownlist control are the same. I did some googling. It seem like this is the common problem. I haven't found any work around yet.
You could use values like this:
1:2
2:2
3:2
Where the second number is the "real" value. Then your event should fire and you can parse out the "real" value in your code behind.
Why do you have a drop down where all of the values are the same? Or is just that some of them are the same?
If you think back to pre ASP.Net days then the only thing that is send with a form submit from a <SELECT> is the VALUE of the <OPTION>. ASP.Net then effectively works out which item is selected by looking up this value in the list of data items.
You will also notice that if you have two items with the same value but different labels that if you do trigger a postback the next time the form loads the first one will be displayed, even if you have the second one selected before you performed the postback.
If you take a step back for a moment and consider your original data source - how would you identify which text value was selected if all you have is the Value? How would you select that value from a database, or from a list? How would you update that row in the database? If you try it you will find that .Net throw an Exception because it cannot uniquely identify the row.
Therefore you need to add a unique key to your data.