I have the MouseDown Event on my XtraGrid, that doesn't want to fire the second time on the same column.
It recognizes the first click, but unless I click another column or row before attempting to click the original row/column, nothing happens.
Can anyone tell me what I am missing? Here is the code in the MouseDown event:
var hitInfo = gridViewSpecialty.CalcHitInfo(e.Location);
if (hitInfo.InRowCell)
{
int nRow = hitInfo.RowHandle;
GridColumn column = hitInfo.Column;
LinkClick(nRow, column);
}
Thanks!! Bob
It's most likely due to the event erroring out. I'd be willing to bet if you put a Try{}catch{} around that statement, you may trap the error.
Here's what I use when trying to capture a user click event with a grid. I use the double-click event, like so:
private void gcMainGrid_DoubleClick(object sender, EventArgs e)
{
try
{
GridControl gc = (GridControl)sender;
DevExpress.Utils.DXMouseEventArgs dxMEA = (DevExpress.Utils.DXMouseEventArgs)e;
GridView gv = (GridView)gc.MainView;
int iRowHandle = gv.CalcHitInfo(dxMEA.X, dxMEA.Y).RowHandle;
//Check to see if the user is on a row.
if (iRowHandle >= 0)
{
//Do something here.
}
catch(Exception ex)
{
if (Debugger.IsAttached)
Debugger.Break();
else
throw(ex);
}
}
That will get me the RowHandle of the row that the user clicks on. I think that's what you're after but I wouldn't use the mouse-down event for that.
Related
I've been searching for a couple of days now and am running into an issue no matter what I've tried. The problem is that I seem to have come across with the perfect storm and I can't get all 3 things working at the same time.
Pagination
Optional Parameters
Parameter Dialog Prompt
So this first method is what I've been using and everything works except it won't Navigate past past 2 (And I've very aware of why navigation doesn't work)
// ##################################################################################################################################################
// METHOD 1: Everything works correctly except you can't go past page 2
protected void Page_Load(object sender, EventArgs e)
{
CrystalReportViewer1.ReportSource = Session["myReportDoc"] as CrystalDecisions.CrystalReports.Engine.ReportDocument;
if (CrystalReportViewer1.ReportSource == null)
{
//Generate the Report Document
Handlers.ReportHandler myReportHandler = new Handlers.ReportHandler();
CrystalDecisions.CrystalReports.Engine.ReportDocument myReportDocument = myReportHandler.GenerateReport("AlarmStatusReport");
Session["myReportDoc"] = myReportDocument; //This is were we save it off for next time
CrystalReportViewer1.ReportSource = myReportDocument;
}
}
So knowing that the common fix is to not use Page Load but use Page_Init instead. This fixes the Navigation... until I open a report that has optional parameters. With those, every time I try to navigate to the next page, instead of it working, the Parameter box re-appears and now requires at least 1 of my Optional Parameters to be filled out. (Each "next Page" reduces the prompt by 1 Optional). But, because I'm being forced to change the Parameters, it "refreshes" the report and I'm back on Page 1.
// ##################################################################################################################################################
// METHOD 2: Works, but not for any report that has Optional Parameters. They become "Required" and keep popping up instead of navigating to the next page
protected void Page_Init(object sender, EventArgs e)
{
CrystalReportViewer1.ReportSource = Session["myReportDoc"] as CrystalDecisions.CrystalReports.Engine.ReportDocument;
if (CrystalReportViewer1.ReportSource == null)
{
//Generate the Report Document
Handlers.ReportHandler myReportHandler = new Handlers.ReportHandler();
CrystalDecisions.CrystalReports.Engine.ReportDocument myReportDocument = myReportHandler.GenerateReport("AlarmStatusReport");
Session["myReportDoc"] = myReportDocument; //This is were we save it off for next time
CrystalReportViewer1.ReportSource = myReportDocument;
}
}
Now, I got real excited, because I got a bit clever and fixed both those issues, by trapping the Navigation and keeping track of the Page myself. EVERYTHING WORKS NOW!!! until I go to the Parameter Dialog prompt and it was totally jacked up.
// ##################################################################################################################################################
// METHOD 3: Everything works correctly except the Prompt Box doesn't Format correcly due to the addition of the added Event Handers
protected void Page_Load(object sender, EventArgs e)
{
CrystalReportViewer1.ReportSource = Session["myReportDoc"] as CrystalDecisions.CrystalReports.Engine.ReportDocument;
if (CrystalReportViewer1.ReportSource == null)
{
//Generate the Report Document
Handlers.ReportHandler myReportHandler = new Handlers.ReportHandler();
CrystalDecisions.CrystalReports.Engine.ReportDocument myReportDocument = myReportHandler.GenerateReport("AlarmStatusReport");
Session["myReportDoc"] = myReportDocument; //This is were we save it off for next time
CrystalReportViewer1.ReportSource = myReportDocument;
//Init our Manual Page Counter to 1
HiddenFieldPageNumber.Value = "1";
}
CrystalReportViewer1.Navigate += CrystalReportViewer1_Navigate; //Simply Adding this event, EVEN IF IT HAS NO CODE, Breaks the style and formating of the Parameter Prompt box.
CrystalReportViewer1.PreRender += CrystalReportViewer1_PreRender;
}
private void CrystalReportViewer1_Navigate(object source, CrystalDecisions.Web.NavigateEventArgs e)
{
//This prevents this event from Incrementing the Page again when the PreRender Event
//below re-sets which page to show.
if (_SkipPageIncrement == true)
{
return;
}
//Whenever the Navigation is used, this Event fires. Here is the problem, there is nothing that actually tells
//us if the user clicked on Previous or Next (or GotoPage for that Matter). So we have to do some guessing here
if (e.CurrentPageNumber == 1 && e.NewPageNumber == 2)
{
//If they pressed "NEXT" we will always get Current = 1 and New = 2 due to the Pagination starting over on the PostBack
//So we INCREMENT our real Page Number Value.
HiddenFieldPageNumber.Value = (Convert.ToInt32(HiddenFieldPageNumber.Value) + 1).ToString();
}
else if (e.CurrentPageNumber == 1 && e.NewPageNumber == 1)
{
//If they pressed "PREV" we will always get Current = 1 and New = 1 due to the Pagination starting over on the PostBack
//So we DECREMENT our real Page Number Value.
HiddenFieldPageNumber.Value = (Convert.ToInt32(HiddenFieldPageNumber.Value) - 1).ToString();
}
}
private void CrystalReportViewer1_PreRender(object sender, EventArgs e)
{
//The Viewer has a method that allows us to set the page number. This PreRender Event is the only
//Event I could find that works. It comes AFTER the Navigate, but before the reports is rendered.
_SkipPageIncrement = true; //The ShowNthPage re-triggers the Navigation, so this prevents it from running again.
CrystalReportViewer1.ShowNthPage(Convert.ToInt32(HiddenFieldPageNumber.Value));
}
As commented above, the moment I add the OnNavigation Event, even if I comment out all the actual code inside, my Prompt box goes from looking like this...
To this (my page as a dark background and you can see that now shows, plus the "OK" button is all jacked up.
I just don't get why trapping the Navigation Event breaks the Prompt box even when the event is not firing (on that first load).
Side note: I'm using VS 2019 with CR 13.0.3500.0
So thanks to the help of a teammate that is more adept on CSS as I am, I have resolved the issue "good enough". So for anyone who wants to use the LOAD event, (Or has to like me), but then loses the ability to use the navigation and wants to use my method, the band-aid for the Crystal Reports Parameter prompt is to simply override their Styling in you Site.css with this...
/*---------------------- Custom CSS for Report Prompt Buttons ----------------------*/
.pePromptButton {
padding-bottom:4.3px;
}
td.pePromptButton {
display: inherit;
}
img {
vertical-align:top;
}
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 have 2 columns I'm working with in an XtraGrid. When Column1's value changes, I'd like to perform some logic and possibly change the value of Column2 and disable Column2 as well. You can see my code below, but I have 3 problems:
My CustomRowCellEdit function seems to run non-stop in the background.
The SetRowValue on Column2 doesn't seem to really happen unless I click away from the row; I need the change to happen as soon as Column1 is changed.
How can I disable within my IF block?
I've added the following Event to a Grid:
this._myGridView.CustomRowCellEdit +=
new DevExpress.XtraGrid.Views.Grid.CustomRowCellEditEventHandler(
this.myGridView_CustomRowCellEdit);
Here is the Event:
private void myGridView_CustomRowCellEdit(object sender, CustomRowCellEditEventArgs e)
{
if (e.Column.FieldName == "Column1" && e.RowHandle >= 0)
{
GridView gv = sender as GridView;
string value1 = gv.GetRowCellValue(e.RowHandle, gv.Columns["Column1"]).ToString();
if (value1 == "something")
{
gv.SetRowCellValue(e.RowHandle, gv.Columns["Column2"], someOtherValue);
// I'd like to disable Column2 in this IF logic.
}
}
}
In the DevX docs, there is a note about the CustomRowCellEdit event that says
Due to the XtraGrid control's infrastructure, the CustomRowCellEdit event fires frequently - each time a cell is refreshed. Therefore, do not implement complex logic for your CustomRowCellEdit event handler...
Given your stated requirements, my approach would be to use the CellValueChanged event instead of CustomRowCellEdit. Your handler could then say something like
private void myGridView_CellValueChanged(object sender, CellValueChangedEventArgs e) {
if (e.Column.FieldName != "Column1") return;
GridView gv = sender as GridView;
if (e.Value == "something") {
gv.SetRowCellValue(e.RowHandle, gv.Columns["Column2"], someOtherValue);
}
}
To make an individual cell non-editable at runtime, see this topic on the DevExpress support site.
how to set readyonly for rows at runtime using Devxpress Grid Contorl.
Essentially what you need to do is handle the grid view's ShowingEditor event, and using the FocusedRowHandle and FocusedColumn properties, decide whether or not to allow editing for the current cell. To disable editing, set the Cancel property of the CancelEventArgs to true.
Hope this helps.
I am creating a dropdownlist called "ddlYears" dynamically like below code:
private void CreateDynamicDDL()
{
ddlYears.Items.Clear();
ddlYears.Items.Add(new ListItem("Year","0"));
for (int k = 0; k < 4; k++)
{
int time = int.Parse(DateTime.Now.Year.ToString());
ddlYears.Items.Add(new ListItem((time-k).ToString(),(k+1).ToString()));
}
}
and I have ddl selectedindexchanged event as below:
protected void ddlYears_SelectedIndexChanged(object sender, EventArgs e)
{
Response.Write(ddlYears.SelectedValue.ToString());
Response.End();
}
In the above code I am trying to write the selected value. But it's working fine, if select the second item which is "2010" (I mean returning selected value as 1) and so on, but if I select first item which is "Year" it's not firing that ddlYears_SelectedIndexChanged event. Please somebody help me
Thanks
If you have "Year" as the first item then by default it is already selected. If you drop down the list and re-select it, it won't call the SelectedIndexChanged method.
Does it work if you select 2010 and then select Year again?
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.