SQL reporting services has a little search box in the top of the report viewer. When used, it finds the search text, navigates to containing page and highlights the text on the page. My question is how can I do this when the report loads.
Currently I have a reportviewer embedded in my page. Is there a method that will find? I am using sql 2008 express and Dot Net 2
For example I send the serial number 1234 to the report so that when it opens it acts like the user searched for the text and finds it for them in the report.
Ed gave me the answer to the url part. http://server/Reportserver?/SampleReports/Product Catalog&rc:FindString=mystring but I still can't figure out the reportviewer.
Here is some of the page code:
using Microsoft.Reporting.WebForms;
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
Int32 iID = Convert.ToInt32(Request.QueryString["ID"]);
String reportsPath = ConfigurationManager.AppSettings["ReportsPath"];
String sReportName = "ReportInvoice";
reportViewer1.Reset();
reportViewer1.ProcessingMode = ProcessingMode.Remote;
reportViewer1.ShowParameterPrompts = false;
reportViewer1.ServerReport.ReportServerUrl = new Uri(ConfigurationManager.AppSettings["ReportViewerUrl"]);
reportViewer1.ServerReport.ReportServerCredentials = new ReportServerCredentials();//http://localhost/reportserver
reportViewer1.AsyncRendering = false;
ReportParameter[] reportParams = new ReportParameter[1];
reportViewer1.ServerReport.ReportPath = reportsPath + sReportName;
reportParams[0] = new ReportParameter("invoiceID", iID.ToString());
reportViewer1.ServerReport.Refresh();
}
}
Thanks in advance.
See this MSDN page (SQL 2005 version, but 2008 is the same, I believe).
I read through alot of the MSDN articles on the web based report viewer and tried several ways to fire off the search but only found this one to work:
First, in code you can set the search text box like so:
TextBox txt;
txt = (TextBox) this.ReportViewer1.Controls[1].Controls[4].Controls[0];
txt.Text = "test";
I did it in the ReportViewer's PreRender event. Position 1 in the first control list is the toolbar control, #4 is the search group control and then in that group the first control is the text box. The second number (4) could vary based on what you are showing / not showing in the toolbar. I was working with the default report viewer settings. It's a hack but it works.
Then I tried firing off the search event myself but this didn't result in the search working although it did fire off the event and with the correct information....
So here's what I did.
I created a javascript function:
<script type="text/javascript">
function OnFirstLoad() {
if (!isPostBack)
document.getElementById('ReportViewer1').ClientController.ActionHandler('Search', document.getElementById('ReportViewer1_ctl01_ctl04_ctl00').value);
}
</script>
I read the source of the .aspx page and found the text "find" and figured out what the client side call was. You will notice the ctl01 & ctl04 and ctl00 follow the same numbering as the server side code. You would need to change this to reflect your code. Again the second one (ctl04) is the one that is likely to change depending on how your toolbar is setup.
I then set the onload event for the body of the page to the javascript function:
<body onload="OnFirstLoad();">
The last trick was to only call this code the first time. So I added this to the page load event of the form code behind:
If (!IsPostBack)
ClientScript.RegisterClientScriptBlock(GetType(), "IsPostBack", "var isPostBack = false;", true);
else
ClientScript.RegisterClientScriptBlock(GetType(), "IsPostBack", "var isPostBack = true;", true);
This creates a variable that the javascript function checks. On the first go round it's false so it calls the report viewers search function, otherwise it's true and doesn't fire.
This is a pretty bad hack in my opinion and fragile. Changes of the report viewer's toolbar settings may require changes to the javascript and the code to set the text box.
I created a report that had several pages and the first hit wasn't until the third page and it went straight to it. From there the next button worked great until the end of the report.
To bad it's not as simple as the windows based report viewer or the server based report viewer. :)
Good Luck!
If you're trying to do this in a form in code behind then you need to find the report viewer object and add an event to the RenderingComplete that implements Find, so something like this:
public Report()
{
InitializeComponent();
rpViewer.RenderingComplete += new RenderingCompleteEventHandler(rpViewer_RenderingComplete);
}
void rpViewer_RenderingComplete(object sender, RenderingCompleteEventArgs e)
{
int x = rpViewer.Find("0", 1);
}
EDIT:
So, since this in a webpage you can't use the WinForms Controls, however, I was able to wire up a little less hacked version using Javascript that klabranche had used.
Here's a code behind class that adds a javascript function to the body of the html to search the report for the search text that you want:
private void SearchReport(ReportViewer rv, string SearchText)
{
TextBox txt = (TextBox)rv.Controls[1].Controls[4].Controls[0];
txt.Text = SearchText;
this.Body.Attributes.Add("onload", "javascript:document.getElementById('" + rv.ClientID +
"').ClientController.ActionHandler('Search', '" + SearchText + "');");
}
If you don't add the search text to the text box, then it won't show the search string in the text box on the report. This also only works for one report, so if you had additional reports you'd need to alter this. Also, for this to work you need to alter the body tag of your html:
<body id="Body" runat="server">
Have a textbox in your report that uses an expression for its background, set something like:
=iif(me.value = Parameters!Highlight.value, "Yellow", "White")
And of course, make a parameter called Highlight. ;)
Rob
Related
I am trying to retrieve whenever the website displays the following message from a jQuery event. Initially this HTML inst displayed in the HTML.
<div id="toast-container" class="toast-top-right"><div class="toast toast-error" aria-live="assertive" style="display: block;"><div class="toast-message">Check email & password.</div></div></div>
My assumption is, that the webBrowser1.DocumentText.Contains is only looking from the initial load of the content.
So I thought maybe some sort of timer would work every 5 seconds, looking to see if the code has changed - but I don't even think this is right as it's checking the code that's already loaded repeatedly?
private void timer2_Tick(object sender, EventArgs e)
{
// Checks for any errors on sign in page
if (webBrowser1.DocumentText.Contains("toast toast-error"))
{
// Toast Notifications
var signinErrorNotification = new Notification("Error", "Please check your email and password are correct.", 50, FormAnimator.AnimationMethod.Fade, FormAnimator.AnimationDirection.Left);
signinErrorNotification.Show();
}
}
How do I go about getting the latest code that's been affected by any jQuery.
P.S. My c# level is beginner.
The Document property should give you what you need.
Notice that the docs for DocumentText say
Gets or sets the HTML contents of the page displayed in the WebBrowser
control.
For Document they say
Gets an HtmlDocument representing the Web page currently displayed in the WebBrowser control.
To me that's saying that DocumentText is like the starting document and Document is the current DOM. Also see https://learn.microsoft.com/en-us/dotnet/framework/winforms/controls/how-to-access-the-managed-html-document-object-model
So I'm working with this form which, at the end, generates a Word document for the user to download, fires off some emails, and then displays a success panel for the user. The problem I'm having is that the .Visible flags don't end up getting changed whenever I call the downloadWordFile() method. Is there something in that method that would be messing with my ability to change visibility of ASP panels? I've tried removing almost every part of this to see where the issue is popping up and I haven't been able to make heads or tails of it. Everything else works fine, it's just this method causing the issue. Thanks in advance for your help!
protected void btnSubmit_Click(object sender, EventArgs e)
{
pnlForm.Visible = false;
pnlSuccess.Visible = true;
email();
adminEmail();
downloadWordFile();
}
protected void downloadWordFile(){
Response.ContentType = "application/msword";
Response.ContentEncoding = System.Text.UnicodeEncoding.UTF8;
Response.Charset = "UTF-8";
Response.Write("<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:w='urn:schemas-microsoft-com:office:word' xmlns='http://www.w3.org/TR/REC-html40'>");
Response.Write("<head>");
Response.Write("<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"\"text/html; charset=UTF-8\"\">");
Response.Write("<meta name=ProgId content=Word.Document>");
Response.Write("</head>");
Response.Write("<body>");
Response.Write("<div class=Section2>");
Response.Write(buildForm());
Response.Write("</body>");
Response.Write("</html>");
Response.AppendHeader("Content-Disposition", "attachment; filename=" + "Generic.doc");
HttpContext.Current.Response.Flush();
}
EDIT 1: I ended up going a different route entirely. Rather than trying to switch panels, generate emails, and generate word files all in one go, I made the submit button switch the panels, and the success panel now shows a preview of the word document to be downloaded and provides the user a chance to make changes. There is a download button on the success panel that generates the emails and downloads the word document. This required minimal changes to the way the code was already set up and solved another problem I was having with the email generation.
A response can only be one thing. You can't respond with page content and a file. You are setting the response to a file so that is how the browser handles the response.
I would handle this situation by the calling a JavaScript function in the button's click event that downloads the file via an IFrame.
First you would need a "download file" page. In the OnLoad event of that page you can call email();, adminEmail(); and downloadWordFile();
The JavaScript click event handler would look something like this.
function DownloadFile() {
var downloadFrame = document.createElement("IFRAME");
if (downloadFrame != null) {
downloadFrame.setAttribute("src", 'DownloadFile.aspx');
downloadFrame.style.width = "0px";
downloadFrame.style.height = "0px";
document.body.appendChild(downloadFrame);
//Set the visibility of pnlForm and pnlSuccess
}
}
EDIT:
Per your comment, I've had to do the same thing. I solved it by posting the form as normal and assembling the form values into a query string. Then use ScriptManager.RegisterStartupScript to add a script that calls the DownloadFile() function when the page loads. The DownloadFile() function takes the query string as a parameter and the DownloadFile.aspx page uses it to get the form data.
So the click event handler would be updated like this.
function DownloadFile(queryString) {
var downloadFrame = document.createElement("IFRAME");
if (downloadFrame != null) {
downloadFrame.setAttribute("src", 'DownloadFile.aspx' + queryString);
downloadFrame.style.width = "0px";
downloadFrame.style.height = "0px";
document.body.appendChild(downloadFrame);
//Set the visibility of pnlForm and pnlSuccess
}
}
I a have a web form with few textboxes,dropdowns and finally towards the end of the page is 4 custom ajax editors. So on page load the focus is always inside the last editor and no way it comes to the first text box or top of page.On each page load the cursor goes inside the last editor control.How to bring the focus inside the first text box?
Below are the few methods i tried
1.<body onload="document.body.scrollTop = 0;">
2. void Page_Init(object sender, EventArgs e)
{
SetFocus(txtReqtitle);
}
for the above while loading the page i could see the focus goes to the desired text box and then it comes to the last custom control.
3. if(!Page.ClientScript.IsStartupScriptRegistered("scrFocus"))
{
string strScript="var txtBox=document.getElementById('" + txtReqtitle.ClientID.ToString() +"');txtBox.focus();";
ClientScript.RegisterStartupScript(this.GetType(),"scrFocus", strScript,true);
}
4.
function setFocus() {
document.getElementById("txtReqtitle").focus();
}
5. ScriptManager.GetCurrent(this.Page).SetFocus(txtReqtitle);
Any ideas? Thanks..
Seems focus property is not working in load event because of ajax editors
Please add txtReqtitle.Focus() in Page Prerendercomplete() event and let me know whether it works
found the solution which worked for me .would like to share it .. its simple ..just make the autofocus=false for the control.
using jquery
$(document).ready(function(){
$('#<%= txtReqtitle.ClientID %>').focus();
});
The issue I am having is I have a WebBrowser control called "Browser." The browser is populated from a different controls created by MEF:
//Apply Button that cretes the HTML that is loaded into the Browser
btnCreateHTMLPreview(object sender, RoutedEventArgs e)
{
//Clears the content of the observable collection
contents.Clear();
//usedControls is an observable collection of all loaded controls in the stack panel
foreach(var control in usedControls)
control.CreateHTML();
}
//Code in the MEF Control that creates the HTML that is will be loaded into the browser
CreateHTML()
{
string tempStuff = null;
tempStuff += "<h1>" + MyControl.lblHeader.Content + "</h1>\n";
tempStuff += MyControl.txtTextGoesHere.Text + "\n";
//Give the HTML back to the Application
parent.AcceptReport(tempStuff);
}
//Application side where it accepts the HTML and loads it into the Browser
AcceptHTML(string passedInContent)
{
//Observable collection that holds the content of all possible MEF Controls
contents.Add(passedInContent);
string tempStuffForBrowser = null;
tempStuffForBrowser = "<html>\n";
tempStuffForBrowser += "<body>\n";
//Add the content that was saved earlier
foreach (var strInd in contents)
tempStuffForBrowser += strInd;
tempStuffForBrowser = "<html>\n";
tempStuffForBrowser += "<body>\n";
Browser.NavigateToString(tempStuffForBrowser);
}
I did my best above to try and provide the meat of how I am populating the html and add that back into the browser. If there is anything that is unclear please just let me know.
If I have just one control added so that "content" only has the one control in it when I click the button to load the html, it works just fine and loads it in. However if I have more than one control loaded, I have to click that button twice to get it to show. I found this extremely bizarre. My attempt to solve this was to check and see if there was content in the Browser before leaving the event, but I am unsure how to do this. If anyone has any suggestions or any other ideas on how to solve this problem please let me know.
It looks like the WebBrowser control has some kind of issue where it doesn't load the first string it gets; I'm assuming there's some initialization that hasn't happened yet. I got it to work by calling
myBrowser.NavigateToString("");
from within the constructor of my class, and then using it from then on worked correctly. Hokey but it works.
I'm using a user control, and added my report viewer and a custom toolbar. I want to create a custom navigation for it aswell, but for some reason when I want to check the total pages to decide whether or not to show the navigation buttons it either returns 0 or "This expression causes side effects and will not be evaluated" error..
I've ran out of ideas and not quite sure where to go from here..
<rsweb:reportviewer
ID="rvReports"
runat="server" ShowToolBar="False"
SizeToReportContent="True" AsyncRendering="false" />
codebehind:
rds = new Microsoft.Reporting.WebForms.ReportDataSource("dsName", myclasstoload());
rvReports.LocalReport.DataSources.Add(rds);
rvReports.PageCountMode = PageCountMode.Actual;
rvReports.LocalReport.Refresh();
rvReports.DataBind();
if (rvReports.LocalReport.GetTotalPages() > 1)
{
liFirst.Visible = true;
liPrevious.Visible = true;
liNext.Visible = true;
liLast.Visible = true;
}
this is all on the databind event in my usercontrol (.ascx). Any help is more than appreciated.
This msdn question is probably your answer, the GetTotalPages() method can't be called until after the report has rendered. The relevant quote:
The report server won't calculate the total page count until rendering the first page of the report. The ReportViewer doesn't request a page rendering from the server until the ASP.Net event PreRender. If you move the GetTotalPages call to a point after the ReportViewer.PreRender event has fired, you should get the behavior you want.
See also the ASP.NET Page Lifecycle for reference.
to get the pages as for me, I had to render the report in pdf, then using pdfreader class from Itextsharp library to get total pages
var bytes=viewer.Render("PDF");
PdfReader reader = new PdfReader(bytes);
var pageCount = reader.NumberOfPages
this works well if you want to render your rdlc in pdf format