I have a TreeNode and each treenode has its own GridView.
There are two methods for SelectedNodeChanged EventHandler.
beforeSelect() : values on the screen that the user sees will be saved.
afterSelect() : when other TreeNode is selected, it calls the corresponding GridView
afterSelect() works good, but the thing is, I can't determine the previous node before the selectedNode, so I can't get the values on GridView.
Any suggestion to find the previous node? Do I need maybe Session thing?
I hope my explanation is understandable..
protected void callTreeView_SelectedNodeChanged(object sender, EventArgs e)
{
if (callTreeView.SelectedNode != null)
{
treeView1_BeforeSelect();
treeView1_AfterSelect();
}
}
The Web page looks like this. So if I click the "New Call", I want the previous Node Depth, which is "New Call 1"
Related
Summary: When trying to hide a custom command button in ASPxGridView command column, it hides the buttons strangely, one of the buton texts appears in the filter row entry, and the button handlers stop working. The error message like "More controls with the DXCBtn_0_9_-1 were found. The FindControl requires unique identifiers of the controls" (loosely translated) appeares.
I am using DevExpress 14.2.3.0, the grid view is nested in another grid views and in ASPxRoundPanels.
Details: The command column contains the following custom buttons...
<dx:GridViewCommandColumn VisibleIndex="9">
<CustomButtons>
<dx:GridViewCommandColumnCustomButton ID="btnClose" Text="Close as done">
</dx:GridViewCommandColumnCustomButton>
<dx:GridViewCommandColumnCustomButton ID="btnReopen" Text="Reopen">
</dx:GridViewCommandColumnCustomButton>
</CustomButtons>
</dx:GridViewCommandColumn>
The buttons are displayed fine (as links) and the following code handles them nicely:
protected void gvMilestoneTasks_CustomButtonCallback(object sender, ASPxGridViewCustomButtonCallbackEventArgs e)
{
ASPxGridView grid = sender as ASPxGridView;
if (e.ButtonID == "btnClose")
{
int milestoneID = Convert.ToInt32(grid.GetRowValues(e.VisibleIndex, "ID"));
DbUtil.ExecuteNonQuery(String.Format("EXEC sp_milestone_tasks_close_open {0}, 0, N'{1}'",
milestoneID, Page.User.Identity.Name));
grid.DataBind();
} else if (e.ButtonID == "btnReopen")
{
int milestoneID = Convert.ToInt32(grid.GetRowValues(e.VisibleIndex, "ID"));
DbUtil.ExecuteNonQuery(String.Format("EXEC sp_milestone_tasks_close_open {0}, 1, N'{1}'",
milestoneID, Page.User.Identity.Name));
grid.DataBind();
}
}
(That is, dedicated SQL stored procedures with different arguments are called [notice the second argument if curious], and the grid.DataBind(); is used to refresh the content of the status column.)
I want to show only one of the buttons. When the row shows the open one, only the Close button should be displayed and active. When the row shows it was closed earlier, only the Reopen button should be visible and active.
I tried to handle visibility in the CustomButtonInitialize event handler (based on the status info -- when the closed is NULL in the database, then it is open; otherwise, the closed contains the datetime of when it was closed):
protected void gvMilestoneTasks_CustomButtonInitialize(object sender, ASPxGridViewCustomButtonEventArgs e)
{
if (e.VisibleIndex == -1)
return;
ASPxGridView grid = sender as ASPxGridView;
if (e.ButtonID == "btnClose")
{
object o = grid.GetRowValues(e.VisibleIndex, "closed");
bool flagVisible = Convert.IsDBNull(o);
e.Visible = flagVisible ? DefaultBoolean.True : DefaultBoolean.False;
}
else if (e.ButtonID == "btnReopen")
{
object o = grid.GetRowValues(e.VisibleIndex, "closed");
bool flagVisible = !Convert.IsDBNull(o);
e.Visible = flagVisible ? DefaultBoolean.True : DefaultBoolean.False;
}
}
I can observe also an error message in the browser in the sense "More controls with the DXCBtn_0_9_-1 were found. The FindControl requires unique identifiers of the controls" (loosely translated) -- this is hidden somewhere deep in the controls; I am not using the FindControl.
Where is the bug hidden?
Thanks for your help.
I think this is a DevExpress bug fixed in version 2014 2.5:
Fix
The reason is that FilterRow behaves as another row of the displayed grid. It is considered to be another visible row. This way the handler should return early also in the case when the cell type is detected as filter.
if (e.VisibleIndex == -1 || e.CellType == GridViewTableCommandCellType.Filter)
return;
Alternatively, that part can be changed to...
if (e.CommandCellType != GridViewTableCommandCellType.Data)
return;
I've some UserControls which are created dynamically, with parameters :
foreach (DataRow dr in drc)
{
question = (from ques in bdd.QUESTION where ques.ID_QUESTION == idQuestion select ques).FirstOrDefault();
List<Object> listParams = new List<Object>();
listParams.Add(question);
AdminQuestion qa = (AdminQuestion)(Controller.LoadControl(Page, "~/UserControls/AdminQuestion.ascx", listParams.ToArray()));
pnl_question_list.Controls.Add(qa);
}
This is a method I found on SoF and it works great.
This method is called when I click on a button, and all my usercontrols are correctly created.
In this usercontrol, I have a button :
<asp:Button ID="btn_validation_modify_question" runat="server" Text="Modifier"
CssClass="clear_left_float_left myBouton myBoutonEnvoyer"
OnClick="btn_validation_modify_question_Click"/>
And my method :
protected void btn_validation_modify_question_Click(object sender, EventArgs e)
{
QUESTION q = (from m in bdd.QUESTION where m.ID_QUESTION == question.ID_QUESTION select m).FirstOrDefault();
q.MESSAGE = txt_modify_question_message.InnerText;
q.ID_THEME = new Guid(ddl_modify_question_theme.SelectedValue);
bdd.ApplyCurrentValues<QUESTION>("QUESTION", q);
bdd.SaveChanges();
}
But when I click on the button, it don't apply the method, and reload the page, like if I didn't have any declared method.
Is there something I don't know? I already used this technique and everything worked...
If you add controls dynamically, you'll normally need to do it on Init or PreInit page events. Otherwise event handlers will never work.
So, dynamically added controls must be programmatically added to the Web page on each and every page visit. The best time to add these controls is during the initialization stage of the page life cycle, which occurs before the load view state stage. That is, we want to have the control hierarchy complete before the load view state stage arrives. For this reason, it is best to create an event handler for the Page class's Init event in your code-behind class, and add your dynamic controls there.
Note You may be able to get away with loading your controls in the
Page_Load
event handler and maintaining the view state properly. It all depends on whether or not you are setting any properties of the dynamically loaded controls programmatically and, if so, when you're doing it relative to the
Controls.Add(dynamicControl)
line. A thorough discussion of this is a bit beyond the scope of this article, but the reason it may work is because the
Controls
property's
Add()
method recursively loads the parent's view state into its children, even though the load view state stage has passed.
Here you have more information.
EDIT
Just to be sure we're talking about the same, here you have how your code should look like
protected void Page_Init(object sender, EventArgs e)
{
...
foreach (DataRow dr in drc)
{
question = (from ques in bdd.QUESTION where ques.ID_QUESTION == idQuestion select ques).FirstOrDefault();
List<Object> listParams = new List<Object>();
listParams.Add(question);
AdminQuestion qa = (AdminQuestion)(Controller.LoadControl(Page, "~/UserControls/AdminQuestion.ascx", listParams.ToArray()));
pnl_question_list.Controls.Add(qa);
}
...
}
PageLoad(){
If(!Page.IsPostBack())
foreach (DataRow dr in drc)
{
question = (from ques in bdd.QUESTION where ques.ID_QUESTION == idQuestion select ques).FirstOrDefault();
List<Object> listParams = new List<Object>();
listParams.Add(question);
AdminQuestion qa = (AdminQuestion)(Controller.LoadControl(Page, "~/UserControls/AdminQuestion.ascx", listParams.ToArray()));
pnl_question_list.Controls.Add(qa);
}
}
Did you try with this solution? And not use Page_Init()?
I have a list of customers, each of which has a list of transactions. What I need to show is the list of customers and the details of their last transaction.
I've retrieved the details into a List of Customer, each with a List of Transaction as a property (called Transactions)
I'm trying to show the data of the transaction, and I thought that I could bind to a data field of Transactions[0].TransactionDate, but the GridView doesn't recognise that. Is there some other syntax, is it not possible, or what's a good workaround for this?
What you need to do is create a gridView rowDataBound event and in this event you can do something like this. The reason for this is as it will give you alot more control over the binding.
protected void gridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
Customer> customer = (Customer)e.Row.DataItem;
Label lblTransaction = ((Label)e.Row.FindControl("LabelTransaction"));
lblTransaction.text = customer.Transactions[0].TransactionDate;
//do what ever you want to do here using the value of your label
}
}
You should be able to cast the dataitem, then read the value from that. e.g.
((YourClassName)Container.DataItem).Transactions[0].TransactionDate
I am playing about just now trying to teach myself a little bit about the entity framework.
I have a Gridview data bound to a Entity Date Source using the Entity Framework. If I select certain items in that list I then wish to redirect another page and populate another gridview with just the items selected (but with more detail, different includes/navigation properties)
This is probably the most simple thing but I have spent 2 hours banging my head on the wall trying to get this to work.
Essentially I have a continue button which when clicked should identify all the UIDs (a column in the gridview) of the rows and allow me to subset to just these rows and pass them to another page to be rebound to another datagrid
Any ideas???
Well, the big picture is that you should get those IDs, pass them to the other page, and then use a query with Contains; see this question for an idea of how to use it:
How search LINQ with many parametrs in one column?
Assuming you haven't used DataKeys in your GridView, this would be my approach.
Page 1
protected void Button1_Click(object sender, EventArgs e)
{
var checkedItems = new List<int>();
foreach (GridViewRow row in GridView1.Rows)
{
var checkbox = (CheckBox)row.FindControl("CheckBox1");
if (checkbox.Checked)
{
checkedItems.Add(int.Parse(row.Cells[1].Text));
}
}
Session["checkedItems"] = checkedItems;
Response.Redirect("Page2.aspx");
}
Page 2
protected void Page_Load(object sender, EventArgs e)
{
var checkedItems = (List<int>)Session["checkedItems"];
Session["checkedItems"] = null;
foreach (var checkedItem in checkedItems)
{
Response.Write(checkedItem);
}
}
Using the IDs in the checkedItems List you can now query those from you DB and finally assign the Result to your GridView on the second page.
Instead of using Session you could pass the IDs via QueryString.
I am developing an online exam application using asp.net. In the start exam page I have created a javascript countdown timer.
How can I move to the next page automatically after the timer reaches 00?
Here is my code:
long timerStartValue = 1000 ;
private int TimerInterval
{
get
{
int o =(int) ViewState["timerInterval"];
if(o==0)
{
return (o);
}
return 50 ;
}
set
{
ViewState["timerInterval"] = value;
}
}
protected void Page_PreInit(object sender,EventArgs e)
{
string timerVal = Request.Form["timerData"];
if(! String.IsNullOrEmpty(timerVal))
{
timerVal = timerVal.Replace(",", String.Empty) ;
this.timerStartValue = long.Parse(timerVal);
}
}
protected void Page_Load(object sender, EventArgs e)
{
if(! IsPostBack)
{
this.timerStartValue = 10000; //3599000;//14400000;
this.TimerInterval = 500;
}
}
protected void Button1_Click(object sender, EventArgs e)
{
this.timerStartValue = 3599000;
}
protected void Page_PreRender(object sender, EventArgs e)
{
System.Text.StringBuilder bldr=new System.Text.StringBuilder();
bldr.AppendFormat("var Timer = new myTimer({0},{1},'{2}','timerData');", this.timerStartValue, this.TimerInterval, this.lblTimerCount.ClientID);
bldr.Append("Timer.go()");
ClientScript.RegisterStartupScript(this.GetType(), "TimerScript", bldr.ToString(), true);
ClientScript.RegisterHiddenField("timerData", timerStartValue.ToString());
}
Thanks in advance,
sangita
It sounds like when you click the "Next" button, you are loading an entirely new page. This of course changes all the content and resets all the javascript. You can't maintain state across pages without a bit of work.
The solution to this could be to save the timer state when the next button is pressed, and pass it to the next stage. You could do this by saving the timer state to a hidden form input and submitting it along with the Next button.
The other option would be to load your questions via AJAX. Instead of moving to a new page every time the next button is clicked, you could simply replace the question portion of the page with a new question, and leave the timer intact. This is probably the solution I would use.
Are u reloading the entire page when clicking on the next button ? That may leads to realod the java script file also.So the variable values will reset.May be you can think about showing the questions /answers via Ajax.You need not reload the entire page when showing the next question.the part when you show the quiz will only be updated.so you can maintain the global variables in your java script too. Check the below link to know about partial page updating using jQuery.
http://www.west-wind.com/presentations/jquery/jquerypart2.aspx
Hope this helps.
You can put the timer in an iframe if you can't get rid of the postback.
You need a way to persist information between pages, and there's really only one possibility: To make it part of the next page request.
Now, this could be subdivided into 2 categories:
1) As part of the url: http://www.example.com/page?timer=123;
2) As part of the headers;
And number 2 opens new possibilities:
a) As part of POST data;
b) As a client-side cookie only;
c) As a cookie tied to information on the server;
Number 1, 2a and 2b can be manipulated by the user. So what you can do is store some value in a cookie, a hash for example or a database row ID, that you'll use to fetch information on the server.
tl;dr? Use a asp "Session object". It lets you keep things on the server-side and users will have no idea what they are.