I have a very annoying problem that I've been struggling with for a few hours now. I have multiple asp.net GridView controls on a page. One of these grids (grid B), is dependent on another grid (grid a) for its data to update correctly.
The problem I have is this:
When I do gridB.Databind() in a if(!IsPostback), then functionality of Grid B works, but the grid doesn't update with newly added records in Grid A.
When I do gridB.Databind() anywhere else that doesn't contain a Postback check, then the data in grid B updates correctly with the newly added records in Grid A, but then the functionality of Grid B no longer works.
Example:
// Functionality for dropdownlist etc works correctly, but new data from gvA doesn't show in gvB
if (grvSender.ID == "gvA")
{
if (!IsPostBack)
gvB.DataBind();
}
// Functionality for dropdownlist etc no longer works correctly, but new data from gvA shows correctly in gvB
if (grvSender.ID == "gvA")
{
if (IsPostBack)
gvB.DataBind();
}
I've called the databind method for gvB in every possible place known to man and the same problem persists...Fix problem A gives me problem B and fixing problem B gives me problem A.
Any ideas would be great. I can see this being something ridiculously silly but I've stared at the code almost all day now and I'm out of ideas.
You should use Page_PreRender event for your code and you can write your code as follow with else as well.
if (grvSender.ID == "gvA")
{
if (!IsPostBack)
gvB.DataBind();
}
else
{
if (IsPostBack)
gvB.DataBind();
}
Related
Good morning,
I wanted to know the best way to refresh a grid after making a change to one of the elements in an edit window.
I have a grid with lets say employees. I pass the employee as reference to the edit window...
EmployeeEdit wEdit = new EmployeeEdit(ref selectedEmployee);
wEdit.Show();
If I delete this employee and come back to the main grid, that employee is still there because the grid has not refreshed (I dont want to do a showdialog).
I was thinking about passing a variable as reference and changing that variable upon deleting an employee. Then, when the original grid got focus, check the variable and refresh the grid if I have to.
This seems like a rigged fix and I wanted to know the most efficient way to do this.
Thank you
You need to subscribe to an event in wEdit object, for example it may have a closing event or a quit event (unfortunately I can't tell from your code).
To subscribe to the event you can write something like this;
EmployeeEdit wEdit = new EmployeeEdit(ref selectedEmployee);
wEdit.Closing += (s, e) =>
{
//place code to refresh your grid here
}
wEdit.Show();
When the event fires it should refresh your grid.
I have a SqlDataSource bound to a GridView with an SQL that takes about 10 seconds to retreive the data.
Also there is a UserControl called "PageSizeControl" which hooks the selected-event of the GridView's SqlDataSource. In this event, I need the DataTable to prepare some settings of the PageSizeControl.
Currently, I'm doing this with following code:
protected void ds_Selected(object sender, SqlDataSourceStatusEventArgs e)
{
SqlDataSourceView dsv = (sender as SqlDataSourceView);
dsv.Selected -= ds_Selected;
DataTable dt = (dsv.Select(DataSourceSelectArguments.Empty) as DataView).Table;
int iRowCount = dt.Rows.Count;
// some gui-adaption like visibility, text, ...
}
In older versions we used e.AffectedRows. But the value stored in e.AffectedRows is not correct when a Filter is applied to the DataSource. And we have use-cases where we don't only need the row count but the whole DataTable.
The problem is, that the .Select() re-executes the Db-Query and this takes another 10s to finish.
I also tried to turn caching on the SqlDataSource on:
EnableCaching="true" CacheDuration="Infinite"
But this wasn't helpful in two reasons:
1. The OnSelected event is not fired when cached data get accessed
2. If the OnSelected event get's fired (because data wasn't yet cached), the .Select() is still executing uncached and takes 10s.
Does anybody have clues how I can get the data without a time-consumpting re-execution of the query? Best would be in the OnSelected, but I'm open for another suggestions.
I got a workaround running that fits my requirements. I use the event GridView.OnRowDataBound and get the DataItem of the first GridRow, which contains the DataTable.
private DataTable oData = null;
protected void gv_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (oData == null && e.Row.DataItem != null)
{
oData = (e.Row.DataItem as DataRowView).Row.Table;
}
}
This solution works, but it looks quite dirty and it requires a GridView (which in my case is no problem). I would be grateful for a more clean solution.
UPDATE
After a longer research with IlSpy I got to the conclusion that it is not possible to get the data in the OnSelected event. Even not if caching is enabled, since cache is written after OnSelected.
So the easiest way is to turn cache on and call the SqlDataSource.Select(...) function where you need the data.
Another way is to get the data by yourself with SqlDataSource.Select(...) and then bind the table it to the controls. But this has some disadvantages. For example: sorting and paging on GridView doesn't work out of the box when bound to a dataset/datatable.
And yet another way is to extract the data from the control which selected it. See above for an example for GridView.
I have stumbled across a problem with my asp.net form.
Within my form the end user chooses a number of textboxes to be dynamically created, this all works fine with the following code:
protected void txtAmountSubmit_Click(object sender, EventArgs e)
{
int amountOfTasks;
int.TryParse(txtAmountOfTasks.Text, out amountOfTasks);
for (int i = 0; i < amountOfTasks; i++)
{
TextBox txtAddItem = new TextBox();
txtAddItem.ID = "txtAddItem" + i;
txtAddItem.TextMode = TextBoxMode.MultiLine;
questionNine.Controls.Add(txtAddItem);
txtList.Add(txtAddItem.ID);
}
}
However this has also caused a small problem for me, later on in my form on the submit button click, I send the results to the specified person it needs to go to (using smtp email). Again this part is fine, until I am trying to retrieve the text from these dynamically created textboxes.
What I have tried
I have tried using this msdn access server controls ID method however this was not working.
I tried to add these new textboxes to a list, however I was unsure on how to update these textboxes when they have text in them. Therefore my results were returning null because of this.
I have also looked at other questions on SO such as this however they are usually for WPF or winforms, rather than my problem with asp.net (this usually isn't an issue, but I don't need to get the text from every textbox control in my page, just the ones that were dynamically created).
I have also tried changing how I call the code that I hoped would have worked:
string textboxesText = string.Join("\n", txtList.Select(x => x).ToArray());
and then in my concatenated string (email body) I would call:
textboxesText
The problem
As they are dynamically created I am finding it difficult to call them by their id for example: txtExampleID.Text, also as I have to increment the ID's by one each time (so they don't override each other) it has made things a little bit more difficult for me.
I am not asking for a code solution, I would prefer pointers in the right direction as I am still learning.
So to sum it all up: I need to get the text from my dynamically created textboxes to add it to my email body.
The issue is these text boxes need recreated in the Load event of the page, every single time, so that both events and values can be hooked back up and retrieved.
I think the most straight forward approach, in your case, would be to extend idea #1 that you had already tried. Build a List of these controls with enough information to recreate them in Load, but you need to store that List in either ViewState or Session.
ViewState["DynamicControls"] = list;
or
Session["DynamicControls"] = list;
I would use ViewState if you can because it gets destroyed when the user leaves the page.
I actually have two questions:
(1) Is it possible to put another image on top of an ImageButton that already has an ImageUrl set (without changing the ImageUrl - literally just add the second image 'on top')? Even by using CSS?
(2) I have a dynamically set number of ImageButtons contained within a ListView. When a user clicks on an ImageButton, I change the .CssClass property of the one clicked in order to 'highlight' it. My question is this: whenever an ImageButton is click, I need to not only highlight it, but make sure I unhighlight all the others. However, I'm having trouble getting the others. I get the clicked ImageButton using
((ImageButton)sender).CssClass = "SelectedImageButton";
in the event handler. However, how do I get all the others so I can set their style 'back' to the unhighlighted style?
Thanks in advance for any help!
UPDATE: ANSWERED!
I've solved the issue mentioned in (2) using the following algorithm. Note, I've marked #OFConsulting's answer below as the correct answer because without his algorithm, I would have never gotten the following algorithm (which came from tweaking his algorithm slightly). Thanks #OFConsulting!
// Cast the sender to an ImageButton to have the clicked ImageButton
ImageButton clickedImageButton = sender as ImageButton;
// The ListView has ListViewDataItems and the ImageButtons are in
// THOSE children controls, thus match on the ImageButtons' Parents' IDs
Control parentControl = clickedImageButton.Parent;
List<ListViewDataItem> allOtherImageButtons = MyListView.Controls.OfType<ListViewDataItem().AsQueryable().Where(i => i.ID != clickedImageButton.Parent.ID).ToList();
// Highlight
clickedImageButton.CssClass = "HighlightedStyle";
// Unhighlight
foreach (ListViewDataItem button in allOtherImageButtons)
{
// The ImageButton is always the 2nd child control of the ListViewDataItem
ImageButton childImageButton = (ImageButton)button.Controls[1];
childImageButton.CssClass = "NoHighlightedStyle";
}
For Part (1) of that question, setting the background image within your css class might do the trick, but you never really explained why you just couldn't change the ImageUrl. You can always throw everything on an update panel if you need it to be dynamic without the hassle of a bunch of script.
Part (2) seems pretty straight forward. Just use a little bit of linq against the relevant control collection within your page.
protected void ImageButton5_Click(object sender, ImageClickEventArgs e)
{
ImageButton clickImageButton = sender as ImageButton;
// This example assumes all the image buttons have the same parent.
// Tweak as needed depending on the layout of your page
Control parentControl = clickImageButton.Parent;
List<ImageButton> allOtherImageButtons = parentControl.Controls.OfType<ImageButton>().AsQueryable().Where(i => i.ID != clickImageButton.ID).ToList();
// Highlight
clickImageButton.CssClass = "WhateverHighlights";
// Unhighlight
foreach (ImageButton button in allOtherImageButtons)
{
button.CssClass = "WhateverClears";
}
}
Edit: One more thing. Make sure any controls you are adding dynamically get added before Page_Load (I.E. during Init). There are some viewstate issues associated with adding control too late.
I have a grid control with unbound columns in it.
The question is, everytime I change a cell value (I am using a repository item) I immediately call the gridview.PostEditor() method so that it would right away update the grid data which requires to be updated everytime I change a specific cell. Keep in mind that I am using the PostEditor() method so that I dont have to lose the focus on a cell first to update the gridview. Anyway, calling the PostEditor() will update my grid (which works fine) and still have the reposiroty item open, a repositoty item spin edit control to be exact, but the thing is if I hit a numeric key, It will discard the old value and replace it with the new one. I don't want it to behave like this. I want it so if the old value is 10.00 and I press the "0" key it will change the value to a "100.00" not back to "0.00".
Please help!
Thanks! :)
I dont know if I understand the question. But I did a search on some of my personal devexpress stuff and found this:
private void riSpinEdit_EditValueChanged(object sender, EventArgs e)
{
TextEdit edit = grdReceiveGoods.FocusedView.ActiveEditor as TextEdit;
if (edit != null)
{
int len = edit.SelectionLength;
int start = edit.SelectionStart;
grdReceiveGoods.FocusedView.PostEditor();
edit.SelectionLength = len;
edit.SelectionStart = start;
}
}
Let me know if this solves your problem.