tag:blogger.com,1999:blog-53060249322654039452024-03-19T18:10:26.591+06:00I Code Therefore I AmMr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.comBlogger29125tag:blogger.com,1999:blog-5306024932265403945.post-23057036437694944962011-03-14T19:32:00.005+06:002011-03-14T20:08:26.807+06:00DD Reports - Advanced interactive charts, part 1<font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>General</b></font><br /><font style="font-family:Tahoma;font-size:10pt">One of the amazing things about charts in <a href="http://www.datadynamics.com/Products/DDRPT/Overview.aspx">Data Dynamics Reports</a> is they may be interactive. You can check out <a href="http://www.datadynamics.com/Products/DDRPT/ScreencastViewer.aspx?ID=CHTDT">chart drillthrough screencast</a> to see this feature in action. But perhaps you need to adjust the way the charts show the subsequent data by displaying the popup window instead of displaying the drillthrough report in the same window? Yes, sir, Data Dynamics Reports allows to do this. In this article we will see how it can be achieved in the windows-forms based report viewer. The next article will give some ideas on how to implement this feature in the web-based report viewer. As usual let's formulate the problem and then solve it step by step.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>The problem</b></font><br /><font style="font-family:Tahoma;font-size:10pt"><a href="http://abakumoff.com/files/blog/charts/DistrictSales.xml">DistrictSales.xml</a>(change extension to rdlx) displays the pie chart of the sales by district. If a user clicks on the piece of pie, then the <a href="http://abakumoff.com/files/blog/charts/storesales.xml">StoreSales.xml</a>(change extension to rdlx) is opened and shows the detailed information about the sales by store in the corresponding district. Now we want to adjust this interactivity - if a user clicks on the piece of pie, then the popup window hosting the sales by store appears. For your convenience I created <a href="http://abakumoff.com/files/blog/charts/AdvancedChartDrillthrough.zip">AdvancedChartDrillthrough.zip</a> we can start with, implementing the requirements step by step. The rest of the article walks through these steps.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>In action</b></font><br /><font style="font-family:Tahoma;font-size:10pt">(1)Open AdvancedChartDrillthrough project in Visual Studio 2008. Adjust the references to DDR assemblies if it's needed, compile and run it. The main form hosts the viewer that displays DistrictSales report with the default interactivity - clicking on the piece of the pie chart shows StoreSales report in the same window. We are about to adjust it.<br /><br />(2)Open the code of MainForm.cs, add the handler of Action event of the viewer before the call to OpenReport method, like below:<br /><pre style="font-size: small;color: black;font-family: Consolas, 'Courier New', Courier, Monospace;background-color: #ffffff;"><br /><span style="color: #0000ff;">public</span> MainForm()<br />{<br /> <span style="color: #008000;">// the rest of the code</span><br /> viewer.Action += viewer_Action;<br /> viewer.OpenReport(<span style="color: #0000ff;">new</span> FileInfo(<span style="color: #006080;">"DistrictSales.rdlx"</span>));<br />}<br /><span style="color: #0000ff;">void</span> viewer_Action(<span style="color: #0000ff;">object</span> sender, DataDynamics.Reports.ActionEventArgs e)<br />{<br />}</pre><br />(3)Action event is raised when a user clicks an interactive element - hyperlink, drill through link or bookmark link. In the handler of Action method you can cancel the default processing and perform the custom steps, like opening the drillthrough reports in the popup window. Let's start with handling action event - we will extract the information about report to jump and set its parameters values:<br /><pre style="font-size: small;color: black;font-family: Consolas, 'Courier New', Courier, Monospace;background-color: #ffffff;"><br /><span style="color: #0000ff;">void</span> viewer_Action(<span style="color: #0000ff;">object</span> sender, ActionEventArgs e)<br />{<br /> <span style="color: #008000;">// we are interested in drill through actions only.</span><br /> <span style="color: #0000ff;">if</span>(e.Action.ActionType==ActionType.DrillThrough)<br /> {<br /> <span style="color: #008000;">// cancel the default processing</span><br /> e.Cancel = <span style="color: #0000ff;">true</span>;<br /> var drillthroughInformation = e.Action.Drillthrough;<br /> <span style="color: #008000;">// get the report to jump</span><br /> ReportRuntime drillthroughReport = drillthroughInformation.ReportRuntime <span style="color: #0000ff;">as</span> ReportRuntime;<br /> <span style="color: #0000ff;">if</span>(drillthroughReport == <span style="color: #0000ff;">null</span>)<br /> <span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> InvalidOperationException(<span style="color: #006080;">"unable to get the drillthrow report!"</span>);<br /> <span style="color: #008000;">// set the parameters if any</span><br /> <span style="color: #0000ff;">for</span>(var i=0;i<drillthroughInformation.NumberOfParameters;i++)<br /> {<br /> drillthroughReport.Parameters[i].CurrentValue = drillthroughInformation.Parameters[i].Value;<br /> }<br /> }<br />}</pre><br />(4) The remaining steps are trivial - we need to open the drillthrough report in the popup form. To do this let's adjust the code of PopupForm.cs - extract "viewer" field and add OpenReport method:<br /><pre style="font-size: small;color: black;font-family: Consolas, 'Courier New', Courier, Monospace;background-color: #ffffff;"><br /><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">partial</span> <span style="color: #0000ff;">class</span> PopupForm : Form<br />{<br /> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">readonly</span> ReportPreview viewer = <span style="color: #0000ff;">null</span>;<br /> <span style="color: #0000ff;">public</span> PopupForm()<br /> {<br /> InitializeComponent();<br /> viewer = <span style="color: #0000ff;">new</span> ReportPreview();<br /> viewer.IsToolbarVisible = <span style="color: #0000ff;">false</span>;<br /> viewer.PageBorder = PageBorder.None;<br /> viewer.Dock = DockStyle.Fill;<br /> viewer.PreviewMode = PreviewMode.Layout;<br /> Controls.Add(viewer);<br /> }<br /> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> OpenReport(ReportRuntime reportRuntime)<br /> {<br /> viewer.OpenReport(reportRuntime, <span style="color: #006080;">"sales by store"</span>);<br /> }<br />}</pre><br />and finally let's show the popup form in viewer_Action handler code(at the end of the method body):<br /><pre style="font-size: small;color: black;font-family: Consolas, 'Courier New', Courier, Monospace;background-color: #ffffff;"><br /><span style="color: #0000ff;">void</span> viewer_Action(<span style="color: #0000ff;">object</span> sender, ActionEventArgs e)<br />{<br /> <span style="color: #008000;">// the rest of the code</span><br /> var popupForm = <span style="color: #0000ff;">new</span> PopupForm();<br /> popupForm.Show();<br /> popupForm.OpenReport(drillthroughReport);<br />}</pre><br />(5)<a href="http://abakumoff.com/files/blog/charts/AdvancedChartDrillthrough_final.zip">AdvancedChartDrillthrough_final.zip</a> the final version of AdvancedChartDrillthrough project.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Next time</b></font><br /><font style="font-family:Tahoma;font-size:10pt">Interactivity involves the popup form on the web-based report viewer is going to be interesting to deal with!</font>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com0tag:blogger.com,1999:blog-5306024932265403945.post-9968280357114318072011-02-17T22:03:00.004+06:002011-02-17T22:27:52.253+06:00Data Dynamics Reports: One touch printing on the web<font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Preface</b></font><br /><font style="font-family:Tahoma;font-size:10pt">Some time ago I <a href="http://icodethereforeiam.blogspot.com/2010/02/few-thoughts-about-no-touch-printing-in.html">blogged</a> around ideas on no-touch printing on the web in <a href="http://www.datadynamics.com/Products/ActiveReports/Overview.aspx">ActiveReports</a>. A lot of the new features were added in both of ActiveReports and <a href="http://www.datadynamics.com/Products/DDRPT/Overview.aspx">Data Dynamics Reports</a> since from that blog post was published. Particularly we have updated PDF export capabilities so that they allow performing <span style="font-style:italic;">one touch printing</span> easily. In this article I will explain it in details.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>The problem</b></font><br /><font style="font-family:Tahoma;font-size:10pt">Let's imagine that we have the <a href="http://abakumoff.com/files/blog/printonopen/default.htm">simple Html page</a>. It hosts the list of the product categories(obtained from <a href="http://msdn.microsoft.com/en-us/library/ms227484%28v=vs.80%29.aspx">Northwind database</a>, Categories table) and "Print" button. We need to implement the following functionality: a user selects the category, clicks Print, the server returns the PDF document that shows the list of the products from the selected category(obtained from Northwind database, Products table), PDF document starts printing immediately - a user should get the print dialog of PDF viewer and the document should not be opened in the viewer.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>One-touch printing in action</b></font><br /><font style="font-family:Tahoma;font-size:10pt">Let's create the web-site that implements the functionality described in "Problem" section:<br /><a href="http://abakumoff.com/files/blog/printonopen/products.xml">products.xml</a>(change the extension to Rdlx) is the report that accepts category id parameter and displays the list of the products accordingly. Copy products.rdlx in the root folder of the web-site.<br />Now copy <a href="http://abakumoff.com/files/blog/printonopen/default.htm">default.htm</a> in the root folder of the web-site and let's look at the page body:<br /><pre style="font-size: small;color: black;font-family: Consolas, 'Courier New', Courier,Monospace;background-color: #ffffff;"><br /><span style="color: #0000ff"><</span><span style="color: #800000">body</span><span style="color: #0000ff">></span><br /><span style="color: #0000ff"><</span><span style="color: #800000">label</span><span style="color: #0000ff">></span>Select the category to print the list of the product of:<span style="color: #0000ff"></</span><span style="color: #800000">label</span><span style="color: #0000ff">><</span><span style="color: #800000">br</span> <span style="color: #0000ff">/></span><br /><span style="color: #0000ff"><</span><span style="color: #800000">select</span> <span style="color: #ff0000">id</span><span style="color: #0000ff">="categoryList"</span><span style="color: #0000ff">></span><br /><span style="color: #0000ff"><</span><span style="color: #800000">option</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="1"</span><span style="color: #0000ff">></span>Beverages<span style="color: #0000ff"></</span><span style="color: #800000">option</span><span style="color: #0000ff">></span><br /><span style="color: #0000ff"><</span><span style="color: #800000">option</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="2"</span><span style="color: #0000ff">></span>Condiments<span style="color: #0000ff"></</span><span style="color: #800000">option</span><span style="color: #0000ff">></span><br /><span style="color: #0000ff"><</span><span style="color: #800000">option</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="3"</span><span style="color: #0000ff">></span>Confections<span style="color: #0000ff"></</span><span style="color: #800000">option</span><span style="color: #0000ff">></span><br /><span style="color: #0000ff"><</span><span style="color: #800000">option</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="4"</span><span style="color: #0000ff">></span>Dairy Products<span style="color: #0000ff"></</span><span style="color: #800000">option</span><span style="color: #0000ff">></span><br /><span style="color: #0000ff"><</span><span style="color: #800000">option</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="5"</span><span style="color: #0000ff">></span>Grains/Cereals<span style="color: #0000ff"></</span><span style="color: #800000">option</span><span style="color: #0000ff">></span><br /><span style="color: #0000ff"><</span><span style="color: #800000">option</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="6"</span><span style="color: #0000ff">></span>GMeat/Poultry<span style="color: #0000ff"></</span><span style="color: #800000">option</span><span style="color: #0000ff">></span><br /><span style="color: #0000ff"><</span><span style="color: #800000">option</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="7"</span><span style="color: #0000ff">></span>Produce<span style="color: #0000ff"></</span><span style="color: #800000">option</span><span style="color: #0000ff">></span><br /><span style="color: #0000ff"><</span><span style="color: #800000">option</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="8"</span><span style="color: #0000ff">></span>Seafood<span style="color: #0000ff"></</span><span style="color: #800000">option</span><span style="color: #0000ff">></span><br /><span style="color: #0000ff"></</span><span style="color: #800000">select</span><span style="color: #0000ff">></span><br /><span style="color: #0000ff"><</span><span style="color: #800000">input</span> <span style="color: #ff0000">id</span><span style="color: #0000ff">="btnPrint"</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">="button"</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="Print"</span> <span style="color: #0000ff">/></span><br /><span style="color: #0000ff"><</span><span style="color: #800000">script</span><span style="color: #0000ff">></span><br /> $(<span style="color: #006080">"#btnPrint"</span>).click(<span style="color: #0000ff">function</span>() {<br /> <span style="color: #0000ff">var</span> catId = $(<span style="color: #006080">"#categoryList"</span>).val();<br /> $(<span style="color: #006080">"#pdfContentPlaceHolder"</span>).attr(<span style="color: #006080">"src"</span>, <span style="color: #006080">"GetData.aspx?catID="</span>+catId);<br /> });<br /><span style="color: #0000ff"></</span><span style="color: #800000">script</span><span style="color: #0000ff">></span><br /><span style="color: #0000ff"><</span><span style="color: #800000">iframe</span> <span style="color: #ff0000">style</span><span style="color: #0000ff">="visibility:hidden"</span> <span style="color: #ff0000">id</span><span style="color: #0000ff">="pdfContentPlaceHolder"</span> <span style="color: #ff0000">width</span><span style="color: #0000ff">="0"</span> <span style="color: #ff0000">height</span><span style="color: #0000ff">="0"</span> <span style="color: #0000ff">/></span><br /><span style="color: #0000ff"></</span><span style="color: #800000">body</span><span style="color: #0000ff">></span></pre><br />So, in the handler of of Print button click we set the source of the invisible frame to the data that are returned by <a href="http://abakumoff.com/files/blog/printonopen/GetData.txt">GetData.aspx</a> page. Once the document is loaded in the frame, the printing should start immediately. How is it achieved? Copy GetData.aspx in the root folder of the web-site and let's look at its Page_Load code:<br /><pre style="font-size: small;color: black;font-family: Consolas, 'Courier New', Courier,Monospace;background-color: #ffffff;"><br /><span style="color: #0000ff">void</span> Page_Load(<span style="color: #0000ff">object</span> sender, EventArgs e)<br />{<br /> <span style="color: #0000ff">int</span> catId;<br /> <span style="color: #0000ff">if</span>(!<span style="color: #0000ff">int</span>.TryParse(Request.QueryString[<span style="color: #006080">"catId"</span>], <span style="color: #0000ff">out</span> catId))<br /> {<br /> Response.Write(<span style="color: #006080">"Invalid category Id parametere value! No output you will get"</span>);<br /> <span style="color: #0000ff">return</span>;<br /> }<br /> var fi = <span style="color: #0000ff">new</span> FileInfo(Server.MapPath(<span style="color: #006080">"~/Products.rdlx"</span>));<br /> var def = <span style="color: #0000ff">new</span> ReportDefinition(fi);<br /> var runtime = <span style="color: #0000ff">new</span> ReportRuntime(def);<br /> runtime.Parameters[0].CurrentValue = catId;<br /> var pdf = <span style="color: #0000ff">new</span> PdfRenderingExtension();<br /> var streams = <span style="color: #0000ff">new</span> MemoryStreamProvider();<br /> var settings = (pdf <span style="color: #0000ff">as</span> IConfigurable).GetSupportedSettings().GetSettings();<br /> <b>settings[<span style="color: #006080">"PrintOnOpen"</span>] = <span style="color: #006080">"true"</span>;</b><br /> runtime.Render(pdf, streams, settings);<br /> Response.ContentType = <span style="color: #006080">"application/pdf"</span>;<br /> Response.AddHeader(<span style="color: #006080">"content-disposition"</span>, <span style="color: #006080">"inline; filename=products.pdf"</span>);<br /> <span style="color: #0000ff">using</span>(var stream = streams.GetPrimaryStream().OpenStream())<br /> {<br /> var len = (<span style="color: #0000ff">int</span>)stream.Length;<br /> var bytes = <span style="color: #0000ff">new</span> <span style="color: #0000ff">byte</span>[len];<br /> stream.Read(bytes, 0, len);<br /> Response.BinaryWrite(bytes);<br /> }<br />}<br /></pre><br />The code is quite trivial, there are two relatively new features in use though:<ul><br /><li>MemoryStreamProvider allows to export the reports to the memory instead of the disk files. It is pretty convenient for web-scenarios where you don't want to use file system aggressively.</li><br /><li>We set PrintOnOpen setting of PDF export to true. It will force PDF document to start printing immediately once it is loaded in the invisible frame on default.htm</li></ul><br />The task is completed.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>ActiveReports</b></font><br /><font style="font-family:Tahoma;font-size:10pt">It is possible to use the same technology in ActiveReports. The setting for PDF export filter document option is called OnlyForPrint, it is hidden in the intellisence, but you can use it:<br /><pre style="font-size: small;color: black;font-family: Consolas, 'Courier New', Courier,Monospace;background-color: #ffffff;"><br />PdfExport pdf = <span style="color: #0000ff">new</span> PdfExport();<br />pdf.PdfDocumentOptions.OnlyForPrint=<span style="color: #0000ff">true</span>;<br /></pre><br /></font>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com0tag:blogger.com,1999:blog-5306024932265403945.post-36448251424055968712011-02-08T20:19:00.004+06:002011-02-08T20:39:21.668+06:00DDR: Using data visualizers to build a thermometer chart<font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Preface</b></font><br /><font style="font-family:Tahoma;font-size:10pt"><a href="http://www.datadynamics.com/Products/DDRPT/Overview.aspx">Data Dynamics Reports</a> does not include circular gauge and meters controls. We did not add them with good reason - they tend to be misleading and and take a lot of space on the screen. Instead we provide Bullet and Sparkline graphs that can visualize data quite effectively. However, as one of our customers <a href="http://www.datadynamics.com/forums/105924/ShowPost.aspx">rightfully mentioned</a>, the sales folks adore meters controls - speedometer, thermometer, etc. and it would be good to have these controls in the product. This article shows how to compose a thermometer chart by using wonderful built-in feature called <a href="http://www.datadynamics.com/Help/ddReports/ddrconDataBar.html">"DataBar visualizer"</a>.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>The problem</b></font><br /><font style="font-family:Tahoma;font-size:10pt">Let's imagine that we are about to build the patients temperature report that is sent to chief of a hospital department every morning. The report shows the table that consists of two columns: patient name and patient temperature that was measured at 6am. The chief demands that the temperature value is visualized by a gauge, like this one:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgehyphenhyphenRhsCbmFr-cgPqjfKvmrOdAK1GeW0KmqgEG8ZWBIjuceWD6DUvZDF-ZV5ZD278r7LZFvHWyUo2IvEu9Zww-M8GDFG9yFyB7gq8l3_iMcZh8RBIJ6NkNINk9vDRNUSKDpLgxsmLiDiRv/s1600/gradusnik.png"><img style="cursor:pointer; cursor:hand;width: 400px; height: 37px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgehyphenhyphenRhsCbmFr-cgPqjfKvmrOdAK1GeW0KmqgEG8ZWBIjuceWD6DUvZDF-ZV5ZD278r7LZFvHWyUo2IvEu9Zww-M8GDFG9yFyB7gq8l3_iMcZh8RBIJ6NkNINk9vDRNUSKDpLgxsmLiDiRv/s400/gradusnik.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5571324120841951266" /></a><br />The thermometer has 3 ranges:<ul><br /><li>[0;35] brushed with blue color - patient has problems or already dead.</li><br /><li>[35;37] brushed with green color - patient is feeling well!</li><br /><li>[37;43] brushed with red color - patient has fever or about to die.</li></ul><br />The yellow marker visualizes the temperature value.<br /></font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>DataBar visualizer in action.</b></font><br /><font style="font-family:Tahoma;font-size:10pt">The rest of the article walks through the process of building the report. For convenience sake the walkthrough starts from the existing report layout that only includes the data are set.<ul><br /><li>Open <a href="http://abakumoff.com//Files/Blog/databar/patientstemperature.xml">PatientsTemperature.xml</a>(change .xml to .rdlx) by using either DataDynamics.Reports.Designer.exe application or Visual Studio.</li><br /><li>Add the <a href="http://www.datadynamics.com/Help/ddReports/ddrconTable.html">table report item</a> in the <a href="http://www.datadynamics.com/Help/ddReports/ddrconLayout.html">report body</a>. Remove the 3rd column and the footer of the table. Set table's DataSetName property to "Temperature" . Set the the 1st column, details row cell value to "=[Patient]"</li><br /><li>Add the Rectangle Report Item in the table's 2nd column, details row cell. Set the rectangle's background color to Green and the name to "rectOuter". This rectangle will show the 2nd range of the thermometer.</li><br /><li>Add the nested rectangle in rectOuter. Set the rectangle's name to "rectNested", the location to (0in,0in), the size to the same value as rectOuter has. Now the magic begins.</li><br /><li>Set the properties of the rectNested BackgroundImage: Source:DataBase, Value:=DataBar(35,0,43,0,'Blue'), MIMEType:image/png, BackgroundRepeat:NoRepeat. What happens here? It's not allowed to set the rectangle's background image by using the data visulalizer editor, like for a textbox, but in fact the rectangle supports data visualizers! What do the DataBar arguments mean? 35 is the boundary of the 1st range, 0 is the minimum temperature value, 43 is maximum temperature value, 0 is the zero coordinate, Blue is the color for the 1st range according to the requirements. <a href="http://www.datadynamics.com/Help/ddReports/ddrconDataBar.html">The documentation</a> describes the arguments meaning in details. Now preview the report. Can you see how the magic works? The rectNested's background image takes the space according to DataBar Value argument. The rest of rectNested is transparent which makes rectOuter's background partially visible. Now our thermomemeter shows 2 ranges. Fantastic!</li><br /><li>Add the nested rectangle in rectNested. Set rectangle's name to "rectNestedNested", location to 0in,0in), size to the same value as rectOuter and rectNested have. As you might deduce rectNestedNested will show the 3rd Red range of our thermometer. Let's set it's background image accordingly:</li><br /><li>Source:DataBase, Value:=DataBar(43,0,43,37,"Red"), MIMEType:image/png, BackgroundRepeat:NoRepeat. In DataBar function we set the zero coordinate to 37 so that the red background starts from the 2nd range right boundary. The magic described in (5) works for the 3rd range as well.</li><br /><li>Now let's add the temperature value marker. It is done by using...drumroll please...rectangle that has DataBar invoke in background image expressions. Add the nested rectangle in rectNestedNested. Set the following properties for this newly added rectangle: Location.Left=0, Size.Width=the same value as the parents rectangles have. Set Location.Top and Size.Height to the appropriate values for the marker. Source:DataBase, Value:=DataBar(Fields!Temperature.Value,0,43,0,"Yellow"), MIMEType:image/png, BackgroundRepeat:NoRepeat.</li><br /><li>Now select rectOuter, rectNested, rectNestedNested and set their rounding radius property to some value, i.e. 0.1in. It will make our pseudo-thermometer look closer to what was shown in the picture above. <a href="http://abakumoff.com//Files/Blog/databar/patientstemperature_final.xml">PatientsTemperature_Final.xml</a>(change .xml to .rdlx) is the sample of the final report version and here is the output sample</li></ul><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYMxHxOtlpfSGil0cgg8Q6_rgk7ThUwa4GbaN1V_RRP95HWMCblQtG14yZevACYmZQFQTF-rATMiDNbpZAPCxgsxkhViFUrsr-f12PNe6dYGxhB7Esy9UKhlxGLuKVXqB6wBC0s239rKbE/s1600/gradusnikOutput000.JPG"><img style="cursor:pointer; cursor:hand;width: 400px; height: 160px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYMxHxOtlpfSGil0cgg8Q6_rgk7ThUwa4GbaN1V_RRP95HWMCblQtG14yZevACYmZQFQTF-rATMiDNbpZAPCxgsxkhViFUrsr-f12PNe6dYGxhB7Esy9UKhlxGLuKVXqB6wBC0s239rKbE/s400/gradusnikOutput000.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5571325748588677362" /></a><br />is this picture informative? Yep, 3 of our 5 patients have fever and it seems that we forgot to move Mr. Jonathan Murraiin to morgue..Whoops!<br /></font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Other scenarios</b></font><br /><font style="font-family:Tahoma;font-size:10pt">By using the same technique you can emulate bullet chart that uses traffic lights colors as described <a href="http://www.datadynamics.com/Help/ddReports/ddrconDataBar.html">here</a>.</font>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com0tag:blogger.com,1999:blog-5306024932265403945.post-41803665398543754812011-02-08T19:30:00.004+06:002011-02-08T20:17:30.537+06:00DDR Excel Export: rendering chart report item as Excel chart object by using the Power of Templates<font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Preface</b></font><br /><font style="font-family:Tahoma;font-size:10pt">Excel Export in <a href="http://www.datadynamics.com/Products/DDRPT/Overview.aspx">Data Dynamics Reports</a> uses the amazing technology called “Templates” behind the scene. When a report is exported in Excel, we first build the intermediate XLS document that contains the placeholders for the actual data. This intermediate document is called “Template”.<br />Then we obtain the data that report normally shows and insert them in the template. The attentive reader will ask - So what? Why is this technology amazing? The answer is we expose the template to the real world: it is possible to obtain the template, modify it and pass to Excel Export. As the result the output may be tuned by creating the custom data placeholders: formulas, pivot tables and so on. In this article we will see how to solve on of the common problems with Excel export by using the Power of Templates.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>The problem: chart output in Excel Export</b></font><br /><font style="font-family:Tahoma;font-size:10pt">If a report contains <a href="http://www.datadynamics.com/Help/ddReports/ddrconChartTypes.html">chart report item</a>, then it is shown as the image in the exported XLS Document. It is not comfortable - Excel has the great charts support and it would be nice to see the DDR chart shown as Excel Chart in the output. Let’s look at hypothetical example. The application displays the attached <a href="http://abakumoff.com//Files/Blog/ExcelTemplates/DelayReport.xml">DelayReport.rdlx(change xml to rdlx)</a> by using the <a href="http://www.datadynamics.com/Help/ddReports/ddrconReportPreview.html">windows forms viewer</a> and allows users to export in Excel(they just click “XLS” button and the resulting document is opened once exportation is done). The report consists of the <a href="http://www.datadynamics.com/Help/ddReports/ddrconTable.html">table</a> and the pie chart that show the data of employees delay statistic. By default the chart is transformed to the picture. The application users are not happy. They demand the Excel Pie Chart in the output. Let’s see what you can do step by step.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Templates power in action</b></font><br /><font style="font-family:Tahoma;font-size:10pt"><ul><br /><li>Open the attached <a href="http://abakumoff.com//Files/Blog/ExcelTemplates/DelayReport.xml">DelayReport.rdlx</a> in the <a href="http://www.datadynamics.com/Help/ddReports/ddrconReportDesigner.html">report designer</a> - either in standalone application or visual studio integrated editor.</li><br /><li>Select Report->Generate Excel Template menu item. Save the template in the appropriate location. Open the generated template in Excel.</li><br /><li>The cell contains “<#Chart1#>” text is the placeholder where the chart picture is going to be inserted, so remove this text, unmerge the cell and decrease its height if it’s needed.</li><br /><li>The cell contains “<#txtReason#>” text is the placeholder for “Reason” column of the table. The values from Reason column will be transformed to the range of cells. This range will start from “<#txtReason#>” cell position and grow further. Let’s name this range: select “<#txtReason#>” cell and define the new named range - in Excel 2007/2010 you can go to Formulas tab, click “Define name”, leave the default values in the popup dialog and click OK.</li><br /><li>The cell contains “<#txtCasesNo#>” text is the placeholder for “CasesNo” column of the table. Name the range it will produce by using the same way as in (4).</li><br /><li>Add the Pie chart on the appropriate place(Excel 2007/2010 - Insert tab, Pie chart). Right click on the chart, choose “Select Data...” and remove the default Legend Entry(Series) value.</li><br /><li>Click Add on Legend Entries(Series) editor. Set Series Name to “Delays”. This will be chart title which equals to one in the original report. Then set Series Values to “=Sheet1.txtCasesNo”. This way you map the chart data to the range created on step (5).</li><br /><li>Click Edit on Horizontal (Category) Axis Labels. Set labels range to “=Sheet1!txtReason”. This way you map the chart labels to the range created on step (4).</li><br /><li>Note that the chart data range is set automatically. Click OK. Save the template. The attached <a href="http://abakumoff.com//Files/Blog/ExcelTemplates/template.xls">template.xls</a> is the sample of the described modifications result.</li><br /><li>Test the exportation with the modified template. For example open the report by using DataDynamics.Reports.Preview.exe, choose Export->Excel in the toolbar. Set Template property in the popup dialog to the template path, select the output file name, click export. The attached <a href="http://abakumoff.com//Files/Blog/ExcelTemplates/output.xls">output.xls</a> shows the example of the output.</li><br /><li>Now in your hypothetical application adjust the code of “XLS” button click handler so that the customized template is used for exportation. Use <a href="http://www.datadynamics.com/Help/ddReports/DataDynamics.Reports.Rendering.Excel~DataDynamics.Reports.Rendering.Excel.ExcelTransformationDevice~TemplateStream.html">TemplateStream property</a>.</li></ul></font><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>The tip of the iceberg</b></font><br /><font style="font-family:Tahoma;font-size:10pt">What is described here is just the small piece of the great functionality that is provided by Excel Export Templates. Basically you can tune the output with any available Excel feature.</font>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com0tag:blogger.com,1999:blog-5306024932265403945.post-6383499289274900642010-11-07T18:57:00.004+06:002010-11-09T20:26:08.131+06:00Async+ActiveReports=AsyncActiveReporting<span style="color: rgb(79, 129, 189);font-family:Tahoma;font-size:12pt;" ><b>Introduction</b></span><br /><span style=";font-family:Tahoma;font-size:10pt;">Autumn is always welcomed as the season of great events in developers world. Autumn of 2010 shed light on the <a href="http://player.microsoftpdc.com/Session/1b127a7d-300e-4385-af8e-ac747fee677a">future of C# and VB.NET</a>. <a href="http://blogs.msdn.com/b/ericlippert/archive/tags/c_2300_+5-0/">Asynchrony support in C# 5.0</a> is what widely discussed nowadays. I would like to make a contribution as well. Let's look at some real-world scenario that makes use of <a href="http://www.datadynamics.com/Products/ActiveReports/Overview.aspx">ActiveReports</a> and analyze how <a href="http://blogs.msdn.com/b/lucian/archive/2010/10/29/a-technical-walk-through-all-of-the-async-ctp.aspx">the new C# 5.0 features</a> can help in the implementation.</span><br /><br /><span style="color: rgb(79, 129, 189);font-family:Tahoma;font-size:12pt;" ><b>The problem</b></span><br /><span style=";font-family:Tahoma;font-size:10pt;">Imagine that you build a WPF application. The UI includes the window with single button "Open Annual Report as PDF". If a user clicks on this button, then of course the annual report which is built by using ActiveReports is <a href="http://www.datadynamics.com/Help/ActiveReports6/arCONPDF.html">exported to PDF</a> and the resulting PDF file is opened in the default PDF viewer that is installed on the system. Here is the XAML, I removed the attributes that don't matter for the discussion:</span><br /><pre style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;margin: 0em;"><br /><span style="color: #0000ff;"><</span><span style="color: #800000;">Window</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">Grid</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">Button</span> <span style="color: #ff0000;">x:Name</span><span style="color: #0000ff;">="btnExport"</span> <span style="color: #ff0000;">Click</span><span style="color: #0000ff;">="btnExport_Click"</span> <span style="color: #0000ff;">></span><br /> Open Annual Report as PDF<span style="color: #0000ff;"></</span><span style="color: #800000;">Button</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"></</span><span style="color: #800000;">Grid</span><span style="color: #0000ff;">></span><br /><span style="color: #0000ff;"></</span><span style="color: #800000;">Window</span><span style="color: #0000ff;">></span><br /></pre><br /><span style=";font-family:Tahoma;font-size:10pt;">Here is the code that performs exportation:</span><br /><pre style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;margin: 0em;"><br /><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">string</span> ExportReportToPdf(<span style="color: #0000ff;">string</span> rpxPath)<br />{<br /> var arReport = <span style="color: #0000ff;">new</span> ActiveReport();<br /> var reader = <span style="color: #0000ff;">new</span> XmlTextReader(rpxPath);<br /> arReport.LoadLayout(reader);<br /> arReport.Run(<span style="color: #0000ff;">false</span>);<br /> var pdfExport = <span style="color: #0000ff;">new</span> PdfExport();<br /> var outFileName = System.IO.Path.GetTempFileName() + <span style="color: #006080;">".pdf"</span>;<br /> pdfExport.Export(arReport.Document, outFileName);<br /> <span style="color: #0000ff;">return</span> outFileName;<br />}<br /></pre><br /><span style=";font-family:Tahoma;font-size:10pt;">And the button click handler:</span><br /><pre style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;margin: 0em;"><br /><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> btnExport_Click(<span style="color: #0000ff;">object</span> sender, RoutedEventArgs e)<br />{<br /> <span style="color: #0000ff;">string</span> pdfFileName = ExportReportToPdf(<span style="color: #006080;">@"C:\AnnualReport.rpx"</span>);<br /> Process.Start(pdfFileName);<br />}<br /></pre><br /><span style=";font-family:Tahoma;font-size:10pt;">This code has the obvious drawback. If the annual report is huge, then its running and export may take a long time. Let's say that the report is SO huge that it takes 1 minute to run and export to PDF(it's hard to imagine though because ActiveReports is super-fast!). Our ExportReportToPdf works in the UI thread and it does not return the control to the caller. It means that UI is not responsive while ExportReportToPdf does its job. This is not acceptable at all. The UI should be responsive. Moreover, it would be nice to allow end-user to cancel the operation and provide some kind of progress report. Indeed .NET framework has all the ammunition that is needed to solve these problems. For example <a href="http://msdn.microsoft.com/en-us/library/waw3xexc.aspx?ppud=4">BackgroundWorker usage example</a> is very similar to what I described above. However, MS realized that using the techniques such as BackgroundWorker is painful - they make use of the background thread, they require quite convoluted code for the cancellation and progress reporting support, they require extra work for updating UI safely and so on. Let's see how we can make UI responsive, provide cancellation and progress reporting support by using the new C# 5.0 features. </span><br /><br /><span style="color: rgb(79, 129, 189);font-family:Tahoma;font-size:12pt;" ><b>All you need is Await and Async</b></span><br /><span style=";font-family:Tahoma;font-size:10pt;">Now let's rewrite the button click handler by using the new C# 5.0 async and await features. Async and Await <a href="http://blogs.msdn.com/b/ericlippert/archive/2010/11/04/asynchrony-in-c-5-0-part-four-it-s-not-magic.aspx">is not magic</a>. It's the syntax sugar for continuation passing style implementation. There are nice blogs that describe how async and await work in details. This post just shows how they can be used in conjunction with the real-world scenario that makes use of ActiveReports. So, here is the async version of the button's click handler: </span><br /><pre style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;margin: 0em;"><br /><span style="color: #0000ff;">async private void</span> btnExportClickAsync(<span style="color: #0000ff;">object</span> sender, RoutedEventArgs e)<br />{<br /> <span style="color: #0000ff;">var</span> task = TaskEx.Run(() => ExportReportToPdf(<span style="color: #006080;">@"c:\AnnualReport.rpx"</span>));<br /> <span style="color: #0000ff;">await</span> task;<br /> Process.Start(task.Result);<br />}<br /></pre><br /><span style=";font-family:Tahoma;font-size:10pt;">And now the UI is responsive while the annual report is run and exported! Doesn't it look much easier to implement than, for example, <a href="http://msdn.microsoft.com/en-us/library/ms228969.aspx?ppud=4">Asynchronous Design Pattern</a>? </span><br /><br /><span style="color: rgb(79, 129, 189);font-family:Tahoma;font-size:12pt;" ><b>What about cancellation?</b></span><br /><span style=";font-family:Tahoma;font-size:10pt;">Now let's add the support for cancellation of report running. In C# 5.0 the long-running task, such as report running or exportation should take care about cancellation. The task is provided with the object that reports whether the cancellation happened. The cancellation may be forced by the timeout or by the explicit invocation of Cancel method of the special object. For example let's add Cancel button to our UI and implement the cancellation support in our long-running task. Here is the updated XAML:</span><br /><pre style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;margin: 0em;"><br /><span style="color: #0000ff;"><</span><span style="color: #800000;">Window</span> <span style="color: #ff0000;">Title</span><span style="color: #0000ff;">="Pending..."</span> <span style="color: #0000ff;">></span><br /><span style="color: #0000ff;"><</span><span style="color: #800000;">Grid</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">Grid.RowDefinitions</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">RowDefinition</span> <span style="color: #0000ff;">/></span><br /> <span style="color: #0000ff;"></</span><span style="color: #800000;">Grid.RowDefinitions</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">Grid.ColumnDefinitions</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">ColumnDefinition</span> <span style="color: #0000ff;">/></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">ColumnDefinition</span> <span style="color: #0000ff;">/></span><br /> <span style="color: #0000ff;"></</span><span style="color: #800000;">Grid.ColumnDefinitions</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">Button</span> <span style="color: #ff0000;">Grid</span>.<span style="color: #ff0000;">Column</span><span style="color: #0000ff;">="0"</span> <span style="color: #ff0000;">Grid</span>.<span style="color: #ff0000;">Row</span><span style="color: #0000ff;">="0"</span> <span style="color: #ff0000;">x:Name</span><span style="color: #0000ff;">="btnExport"</span> <span style="color: #ff0000;">Click</span><span style="color: #0000ff;">="btnExportClickAsync"</span><span style="color: #0000ff;">></span><br /> Export report to PDF<span style="color: #0000ff;"></</span><span style="color: #800000;">Button</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">Button</span> <span style="color: #ff0000;">Grid</span>.<span style="color: #ff0000;">Column</span><span style="color: #0000ff;">="1"</span> <span style="color: #ff0000;">Grid</span>.<span style="color: #ff0000;">Row</span><span style="color: #0000ff;">="0"</span> <span style="color: #ff0000;">x:Name</span><span style="color: #0000ff;">="btnCancel"</span> <span style="color: #ff0000;">Click</span><span style="color: #0000ff;">="btnCancel_Click"</span><span style="color: #0000ff;"> <br /> <span style="color: #ff0000;">IsEnabled</span><span style="color: #0000ff;">="false"</span><span style="color: #0000ff;">></span><span style="color: #000000;">Cancel</span><span style="color: #0000ff;"></</span><span style="color: #800000;">Button</span><span style="color: #0000ff;">></span><br /><span style="color: #0000ff;"></</span><span style="color: #800000;">Grid</span><span style="color: #0000ff;">></span><br /><span style="color: #0000ff;"></</span><span style="color: #800000;">Window</span><span style="color: #0000ff;">></span><br /></pre><br /><span style=";font-family:Tahoma;font-size:10pt;">So, we've added the window title that will indicate the state of the task. It may be "pending", "in progress", "done", "canceled". Those are not standard statuses but rather human-friendly statuses names which I use for the sake of clarity. Also, Cancel button was added and it is disabled when the application starts. There is no anything to cancel before task is run, isn't it?</span><br /><span style=";font-family:Tahoma;font-size:10pt;">Now let's look at the updated code of the Export button click handler:</span><br /><pre style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;margin: 0em;"><br /><span style="color: #0000ff;">private</span> <span style="font-weight:bold;">CancellationTokenSource cancelationObject;</span><br /><span style="color: #0000ff;">async private</span> void</span> btnExportClickAsync(<span style="color: #0000ff;">object</span> sender, RoutedEventArgs e)<br />{<br /> cancelationObject = <span style="color: #0000ff;">new</span> CancellationTokenSource();<br /> <span style="color: #0000ff;">try</span><br /> {<br /> <span style="color: #0000ff;">this</span>.Title = <span class="str">"In progress..."</span>;<br /> btnExport.IsEnabled = <span style="color: #0000ff;">false</span>;<br /> btnCancel.IsEnabled = <span style="color: #0000ff;">true</span>;<br /> <span style="color: #0000ff;">var</span> task = TaskEx.Run(() => ExportReportToPdf(<span class="str">@"C:\AnnualReport.rpx"</span>));<br /> <span style="color: #0000ff;">await</span> task;<br /> <span style="color: #0000ff;">this</span>.Title = <span class="str">"Done"</span>;<br /> Process.Start(task.Result);<br /> }<br /> <span style="color: #0000ff;">catch</span> (OperationCanceledException)<br /> {<br /> <span style="color: #0000ff;">this</span>.Title = <span class="str">"Canceled"</span>;<br /> }<br /> <span style="color: #0000ff;">finally</span><br /> {<br /> cancelationObject = <span style="color: #0000ff;">null</span>;<br /> btnExport.IsEnabled = <span style="color: #0000ff;">true</span>;<br /> btnCancel.IsEnabled = <span style="color: #0000ff;">false</span>;<br /> }<br />}<br /></pre><br /><span style=";font-family:Tahoma;font-size:10pt;">So, we initialize and pass the "cancellation object" in our long-running task(through the class field) and catch the OperationCanceledException. If it is thrown, then the task was canceled. But who performs the actual cancellation? As I mentioned, In C# 5.0 the long-running task, such as report running or exportation should take care about cancellation. The idea: let's intercept the PageStart event of ActiveReport object and cancel the report running if it is needed. We need to update the code of ExportReportToPdf method:</span><br /><pre style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;margin: 0em;"><br /><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">string</span> ExportReportToPdf(<span style="color: #0000ff;">string</span> rpxPath)<br />{<br /> <span style="color: #0000ff;">var</span> arReport = <span style="color: #0000ff;">new</span> ActiveReport();<br /> <span style="color: #0000ff;">var</span> reader = <span style="color: #0000ff;">new</span> XmlTextReader(rpxPath);<br /> arReport.LoadLayout(reader);<br /><span style="font-weight:bold;"> arReport.PageStart += (s, a) => cancelationObject.Token.ThrowIfCancellationRequested();<br /></span> <span style="color: #008000;">// the rest of the code</span><br />}<br /></pre><br /><span style=";font-family:Tahoma;font-size:10pt;">The last think to get cancellation working. Remember about Cancel button? Let's make it do its job!: </span><br /><pre style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;margin: 0em;"><br /><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> btnCancel_Click(<span style="color: #0000ff;">object</span> sender, RoutedEventArgs e)<br />{<br /> <span style="font-weight:bold;">cancelationObject.Cancel();</span><br />}<br /></pre><br /><span style=";font-family:Tahoma;font-size:10pt;">So, the entire picture of cancellation support is: The UI is responsive while the report running and exportation does its job. The user may click Cancel button and it tells "cancel the task!" to the special object. The report running intercepts the new page start event and tells "throw the cancellation exception if you told to do that!" to the special object. The task running catches the "cancellation exception" and updates the UI accordingly. The only drawback here is we can't cancel the task when the exportation starts(PdfExport.Export method is called). We only can cancel the task while the report is run. Unfortunately Export method does not raise any events that we can intercept. Also, the report running can be canceled only when the new page starts processing. Note though that the API I use lives since from ActiveReports 1.0 version(which was born in past century) but we talk about C# 5.0.</span><br /><br /><span style="color: rgb(79, 129, 189);font-family:Tahoma;font-size:12pt;" ><b>Progress reporting</b></span><br /><span style=";font-family:Tahoma;font-size:10pt;">Let's add the last gorgeous feature in our application. We will keep the user informed about the status of the task. The idea is very similar to the cancellation mechanism: we have the special Progress object, we report to that object in the handler of PageStart event of the report, we intercept the event of that object, we get the progress report in the handler, we update the UI with the progress report. All those actions happen in UI thread, we don't need to care about the safe UI updates. Let's look at the code(I removed the parts that do not matter for progress reporting:</span><br /><pre style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;margin: 0em;"><br /><span style="font-weight:bold;"><span style="color: #0000ff;">private</span> EventProgress<<span style="color: #0000ff;">int</span>> progress = <span style="color: #0000ff;">new</span> EventProgress<<span style="color: #0000ff;">int</span>>();<br /></span><br /><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">string</span> ExportReportToPdf(<span style="color: #0000ff;">string</span> rpxPath)<br />{<br /> <span style="color: #0000ff;">var</span> arReport = <span style="color: #0000ff;">new</span> ActiveReport();<br /> <span style="color: #0000ff;">var</span> reader = <span style="color: #0000ff;">new</span> XmlTextReader(rpxPath);<br /> arReport.LoadLayout(reader);<br /> <span style="color: #0000ff;">int</span> pageCount = 0;<br /> arReport.PageStart += (s, a) =><br /> {<br /> cancelationObject.Token.ThrowIfCancellationRequested();<br /><span style="font-weight:bold;"> (progress <span style="color: #0000ff;">as</span> IProgress<<span style="color: #0000ff;">int</span>>).Report(pageCount++);<br /></span> };<br /> <span style="color:#008000">// the rest of the code</span><br />}<br /> <br />async <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> btnExportClickAsync(<span style="color: #0000ff;">object</span> sender, RoutedEventArgs e)<br />{<br /> cancelationObject = <span style="color: #0000ff;">new</span> CancellationTokenSource();<br /> <span style="color: #0000ff;">try</span><br /> {<br /> <span style="color: #0000ff;">this</span>.Title = <span style="color: #006080;">"In process..."</span>;<br /> btnExport.IsEnabled = <span style="color: #0000ff;">false</span>;<br /> btnCancel.IsEnabled = <span style="color: #0000ff;">true</span>;<br /> var task = TaskEx.Run(() => ExportReportToPdf(<span style="color:#006080">@"C:\AnnualReport.rpx"</span>));<br /><span style="font-weight:bold;"> progress.ProgressChanged += (s, args) => <br /> { <br /> <span style="color: #0000ff;">this</span>.Title = <span style="color:#006080">"Pages done: "</span> + args.Value.ToString(); <br /> };<br /></span> await task;<br /> <span style="color:#008000">// the rest of the code</span><br />}<br /></pre><br /><span style=";font-family:Tahoma;font-size:10pt;">Voilà! We've made the UI responsive, added cancellation and progress reporting support for our long-running report task by using the new C# 5.0 features. And they look very comfortable to use so far. The code is clean and very readable(at least I believe in that :-)) </span><br /><br /><span style="color: rgb(79, 129, 189);font-family:Tahoma;font-size:12pt;" ><b>Next time</b></span><br /><span style=";font-family:Tahoma;font-size:10pt;">Now let's imagine that we want to merge two huge reports and export the resulted document in PDF. How we can start two reports at the same time and have the UI responsive and await until both of them are completed? C# 5.0 may help too! Look for the Next episode of AsyncActiveReporting in 1 week :)</span>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com0tag:blogger.com,1999:blog-5306024932265403945.post-69890162895970597392010-06-06T18:52:00.004+07:002010-06-06T20:06:36.197+07:00Data Dynamics Reports And Twitter<font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Preface</b></font><br /><font style="font-family:Tahoma;font-size:10pt">Tips and tricks series continues! In this post I am going to explain how a <a href="http://www.datadynamics.com/Products/DDRPT/Overview.aspx">Data Dynamics Reports</a> report might be set up in order to show the tweets from arbitrary user's public timeline. The live demo is available <a href="http://aspspider.net/sAbakumoff/TwitterData.aspx">here</a>. I can imagine the real-world usage of this feature: say I am HR department manager and in the CV overview report I would like to see the last 3 tweets from the public timeline of the candidates for opened job position. Let's see how a developer can implement such a feature using Data Dynamics Reports.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Using XML Data Provider</b></font><br /><font style="font-family:Tahoma;font-size:10pt">Data Dynamics Reports includes <a href="http://www.datadynamics.com/Help/ddReports/ddrconDataSetAndObjectDataSource.html">XML data provider</a> that can load the data from various sources, particularly it supports xml documents that are located in a web-accessible location. In other hand a user's public timeline can be accessed via RSS feed which is xml document that is located in a web-accessible location. I.e. my public timeline can be read on http://twitter.com/statuses/user_timeline/sAbakumoff.rss. RSS feed document has well known structure: each tweet is presented by <item> tag, its child <description> tag has the tweet text. So...displaying user's public timeline in Data Dynamics Report is pretty simple:<br />1) <a href="http://www.datadynamics.com/Help/ddReports/ddroriReportDataSourceSmartPanel.html">Add new Data Source</a> in a report. Set Data Source type to XML.<br />2) Set the <a href="http://www.datadynamics.com/Help/ddReports/ddrconDataSourceConnectionStringTab.html">connection string</a> of the newly added data source to "xmldoc=http://twitter.com/statuses/user_timeline/USER NAME.rss"(without quotes). Change USER_NAME to the real-world value.<br />3) <a href="http://www.datadynamics.com/Help/ddReports/ddrdoriDataset.html">Add the new Data Set</a> in the Data Source.<br />4) Set the <a href="http://www.datadynamics.com/Help/ddReports/ddrdconDatasetQueryTab.html">Query</a> of the newly added Data Set to "/rss/channel/item"(without quotes).<br />5) Add the <a href="http://www.datadynamics.com/Help/ddReports/ddrdconDatasetFieldsTab.html">Fields</a> to the newly added data set. Set the name of the field to "title", set the value of the field to "title".<br />6) Add <a href="http://www.datadynamics.com/Help/ddReports/ddrconList.html">the List report</a> item in the report, set the DataSetName to the name of the data set that is added in step 3.<br />7) Drag the field "title" from the data explorer to the newly added List Report Item.<br />8) Preview the report, hey presto, it shows the user's public timeline!<br /></font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Advanced techniques</b></font><br /><font style="font-family:Tahoma;font-size:10pt">I've used a couple of other features in the live demo:<br />1) To limit the tweets list for 5 last messages, I used <a href="http://www.datadynamics.com/Help/ddReports/ddrtskFilterDataset.html">TopN filter of the data set</a>. I've added one more field to the data set, it's pubDate. The filter expression is "=Fields!pubDate.Value", the filter operator is TopN, the filter value is 5.<br />2) I parametrized data source query to allow set user name using the <a href="http://www.datadynamics.com/Help/ddReports/ddrconParameters.html">report parameter</a> value, the connection string is set to<br />="xmldoc=http://twitter.com/statuses/user_timeline/" & Parameters!TwitterUser.Value & ".rss"<br />The complete report is available <a href="http://aspspider.net/sAbakumoff/TwitterData.rdlx">here</a>. <br /></font>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com0tag:blogger.com,1999:blog-5306024932265403945.post-72049651800048308562010-05-24T09:39:00.006+07:002010-05-24T13:54:27.360+07:00Data Dynamics Reports: Customizing web-viewer toolbar<font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Preface</b></font><br /><font style="font-family:Tahoma;font-size:10pt">In this post I would like to share the tips and tricks for <a href="http://www.datadynamics.com/Products/DDRPT/Overview.aspx">Data Dynamics Reports</a> <a href="http://www.datadynamics.com/Help/ddReports/ddrconWebViewer.html">Web-based report viewer</a>(hereafter referred to as "Web-Viewer") customization. Web-Viewer component does provide a developer with customization capabilities, but the are a couple of the problems with them - they are tricky to implement and not documented. I hope that this post partly solves those problems.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Web-Viewer overview</b></font><br /><font style="font-family:Tahoma;font-size:10pt">Web-Viewer is the <a href="http://www.w3schools.com/aspnet/aspnet_controls.asp">ASP.NET server control</a> that renders the HTML content in a client side. The HTML content consists of several logical parts - the toolbar, the side panel, the page viewer and the controller. The controller is the javascript object has the methods and properties that allow to load the report to display, navigate through the pages of a report, print a report, export a report to one of the supported formats, etc. All those actions are performed via <a href="http://en.wikipedia.org/wiki/Ajax_%28programming%29">AJAX requests/responses</a> and updating the DOM of the HTML content at run-time.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Toolbar customization</b></font><br /><font style="font-family:Tahoma;font-size:10pt">This post is intended to demonstrate how a developer can make-use of home-grown toolbar for Web-Viewer. The implementation can be split to the following steps:<ol><li>Hiding the built-in toolbar</li><li>Get access to the methods and properties of controller object</li><li>Determine when a report page is loaded to update the custom toolbar</li></ol>I will go through all those steps. However I need to clarify the code ammunition that will be used for the live demo. It is available <a href="http://aspspider.net/sAbakumoff/CustomToolbar.aspx">here</a>, the complete source code can be obtained <a href="http://aspspider.net/sAbakumoff/CustomToolbar_source.htm">here</a>. I tested the live demo on IE8, FireFox 3.6.3 and the last version of <a href="http://www.google.com/chrome/">Google Chrome</a>. The demo works best on Chrome :) </font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>JQuery and LiveQuery</b><br /></font><font style="font-family:Tahoma;font-size:10pt"><a href="http://jquery.com/">JQuery</a> is essential choice for a web-developer. I used JQuery <a href="http://api.jquery.com/category/selectors/">selectors</a>, <a href="http://api.jquery.com/category/manipulation/">element manipulations</a>, the <a href="http://jqueryui.com/demos/button">UI button element</a> to build the live demo. That is expected. However, there is the problem that can't be solved by using the default JQuery library. Web-Viewer component can be added into an aspx page by writing something like <dd:WebReportViewer ID="WebReportViewer1" ReportName="~/Report.rdlx" /> Once an aspx page is requested, web-viewer component starts rendering of the HTML content that has the toolbar, side panel, etc. None of those element exists at design time when a developer builds an aspx page. Therefore the code needs to access to the elements that will be added at-runtime by updating the DOM of the HTML document! Fortunately there is nice <a href="http://brandonaaron.net/code/livequery/docs">Live Query plugin</a> that <span style="font-style:italic;">"utilizes the power of jQuery selectors by binding events or firing callbacks for matched elements auto-magically, even after the page has been loaded and the DOM updated"</span>. This is exactly what we need. To operate on non-existing element a developer writes something like $('#ID').livequery(function(){/*do something*/}); and the code in the brackets executes once the element with id=ID appears on the DOM. </font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Hiding the built-in toolbar</b></font><br /><font style="font-family:Tahoma;font-size:10pt">The built-in Web-Viewer toolbar is the HTML element that has ID="reportViewerToolbar{Web-Viewer componentID}$coreViewer". For example if the ID of Web-Viewer component on the aspx page is "WebReportViewer1" then the ID of the toolbar will be "reportViewerToolbarWebReportViewer1$coreViewer". To hide the built-in toolbar, we can use the following code:<pre style="font-size:small;font-family: Consolas, 'Courier New', Courier, Monospace;"><br />$(<span style="color: #006080;">'#reportViewerToolbarWebReportViewer1\\$coreViewer'</span>).livequery(<span style="color: #0000ff;">function</span> () {<br /> $(this).css(<span style="color: #006080;">'display'</span>, <span style="color: #006080;">'none'</span>);<br />});</pre>So, when Web-Viewer component will render the built-in toolbar, this magic code will update its style with "display:none", and the toolbar will disappear from the page.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Get access to the methods and properties of controller object</b></font><br /><font style="font-family:Tahoma;font-size:10pt">Web-viewer component renders the script code that creates the instance of the controller class. Once this code is executed, the instance is available for the rest HTML page code. The name of the instance is "controller{Web-Viewer componentID}$coreViewer". For example if the ID of Web-Viewer component on the aspx page is "WebReportViewer1" then the name of the controller instance will be "controllerWebReportViewer1$coreViewer". Here is the table of the methods and properties of the controller class. A developer can make use of them on the script code:<table style="border:1px solid #4F81BD" cellspacing="0px" cellpadding="0px"><tr><td><span style="font-weight:bold;">Method</span></td><td><span style="font-weight:bold;">Action</span></td></tr><br /><tr><td>nextPage()</td><td>goes to the next page of a report</td></tr><tr><td>previousPage()</td><td>goes to the previous page of a report</td></tr><tr><td>firstPage()</td><td>goes to the first page of a report</td></tr><tr><td>lastPage()</td><td>goes to the last page of a report</td></tr><tr><td>toggleSideBar()</td><td>Shows or hides the side panel</td></tr><tr><td>print()</td><td>Prints the report</td></tr><tr><td>openPageSetupDialog()</td><td>Opens the dialog allows to set up the page properties</td></tr><tr><td>toggleRenderMode()</td><td>Switched the preview mode to Galley or Print Preview</td></tr><tr><td>backToParent()</td><td>Returns to the parent of the drillthrough report</td></tr><tr><td>openEmailDialog()</td><td>Displays the dialog that allows to send a report via email</td></tr><tr><td>showDocMapSideBar()</td><td>Opens the TOC tab of the side panel.</td></tr><tr><td>showFindSideBar()</td><td>Opens the Search tab of the side panel.</td></tr><tr><td>showParameterSideBar()</td><td>Opens the Parameters tab of the side panel.</td></tr><br /></table><br />For example, to create the Next Page button of my custom toolbar I can use the following code:<pre style="font-size:small;font-family: Consolas, 'Courier New', Courier, Monospace;"><br />$(<span style="color: #006080;">'#btnNextJ'</span>).button().click(<br /> <span style="color: #0000ff;">function</span> () { controllerWebReportViewer1$coreViewer.nextPage(); }<br />);</pre>Also, controller instance has report property. The type of this property is the class that represents the currently displayed report. The report object also exposes useful methods and properties:<br /><table style="border:1px solid #4F81BD" cellspacing="10px" cellpadding="0px"><tr><td><b>Method,Property</b></td><td><b>Action</b></td></tr><tr><td>export(format)</td><td>Exports report to the certain format. Possible parameter values are: PDF, Word, Xml, Mhtml, Excel</td></tr><tr><td>pageCount</td><td>gets the number of pages in a report</td></tr><tr><td>pageNumber</td><td>gets the number of the currently displayed page</td></tr></table><br /><br />For example, to create the Export to PDF button of my custom toolbar I can use the following code:<pre style="font-size:small;font-family: Consolas, 'Courier New', Courier, Monospace;"><br />$(<span style="color: #006080;">'#btnExportPDF'</span>).button().click(<br /> <span style="color: #0000ff;">function</span> () { controllerWebReportViewer1$coreViewer.report.exportReport("PDF"); }<br />);</pre>See the complete sample of code on the <a href="http://aspspider.net/sAbakumoff/CustomToolbar_source.htm">live demo source</a> page.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Determine when a report page is loaded to update the custom toolbar</b></font><br /><font style="font-family:Tahoma;font-size:10pt">This is the most tricky part of the implementation. The problem is the controller instance and its report property value are not initialized until the AJAX request for a report is completed. There is no well-known way to catch this moment. We need to use a work-around this issue. In HTML mode of Web-Viewer the report pages are displayed inside the frame element has ID="CorePanel{Web-Viewer componentID}$coreViewer". For example if the ID of Web-Viewer component on the aspx page is "WebReportViewer1" then the ID of the frame will be "CorePanelWebReportViewer1$coreViewer". JQuery allows to catch the moment when the frame is loaded using load function. In the live demo I use this trick to update the toolbar - to enable the buttons that are disabled by default, to set page number and page count text:<pre style="font-size:small;font-family: Consolas, 'Courier New', Courier, Monospace;">$(<span style="color: #006080;">'iframe[id="CorePanelWebReportViewer1\\$coreViewer"]'</span>).livequery(function () {<br />$(<span style="color: #0000ff;">this</span>).load(<span style="color: #0000ff;">function</span> () {<br /> updateToolbar();<br /> });<br />});</pre>See the code of updateToolbar function on the <a href="http://aspspider.net/sAbakumoff/CustomToolbar_source.htm">live demo source</a> page.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Behind the discussed topics.</b></font><br /><font style="font-family:Tahoma;font-size:10pt">All the tips and tricks I talked about this post work for HTML mode of Web-Viewer. I did not test them for PDF mode, however I am confident that all but the catch of report loaded event works in PDF. I did not try to customize the search, toc and parameters tabs of the side panel, but it might be done using the same techniques as for toolbar customizing.</font>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com0tag:blogger.com,1999:blog-5306024932265403945.post-9642301631147811812010-04-18T22:26:00.002+07:002010-04-19T23:58:21.551+07:00ActiveReports: Show the Data from the Windows Azure Table Storage<font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Preface</b></font><br /><font style="font-family:Tahoma;font-size:10pt">Some time ago I <a href="http://icodethereforeiam.blogspot.com/2010/03/data-dynamics-reports-show-data-from.html">blogged</a> about using <a href="http://www.datadynamics.com/Products/DDRPT/Overview.aspx">Data Dynamics Reports</a> to visualize the data that are stored in Windows Azure Table Storage. Originally I planned to compose that blog post around both of Data Dynamics Reports and <a href="http://www.datadynamics.com/Products/ActiveReports/Overview.aspx">ActiveReports</a> but then I found that the latter has the issues with running against a cloud environment. But ActiveReports team did the great job for preparing Service Pack 1 which includes the fix for those issues! And this blog post repeats the "show the table storage data" walkthrough for ActiveReports6 SP1. I believe that it will be useful for someone. </font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Windows Azure Table Storage</b></font><br /><font style="font-family:Tahoma;font-size:10pt">Windows Azure Table Storage differs from the tables in a relational database. Table storage is object-oriented and saves the entities and the entity properties. The details of table storage is not the subject of this post. I believe that the best way to show how ActiveReports can be used with the table storage is going through the live example. This walkthrough is based on <a href="http://blogs.msdn.com/jnak/archive/2008/10/28/walkthrough-simple-table-storage.aspx">the post</a> in <a href="http://blogs.msdn.com/jnak/default.aspx">"Cloudy in Seattle" blog</a>. However, that blog post sample uses Windows Azure SDK 1.0 and I used the newer version 1.1. A few things was changed in version 1.1, I highlighted them later in this post.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Walkthrough</b></font><br /><font style="font-family:Tahoma;font-size:10pt">This walkthrough is totally based on <a href="http://blogs.msdn.com/jnak/archive/2008/10/28/walkthrough-simple-table-storage.aspx">"Windows Azure Walkthrough: Table Storage"</a>. I just aligned it with the changes in Windows Azure SDK v1.1 and added the steps for show the data using ActiveReports.<br />(1) <a href="http://www.microsoft.com/windowsazure/getstarted/">Get started with Windows Azure</a> - install the prerequisites and SDK v1.1. Install the <a href="http://www.datadynamics.com/forums/83/ShowForum.aspx">latest release of ActiveReports6</a>.<br />(2) Download and extract Windows Azure Additional Samples from <a href="http://code.msdn.microsoft.com/windowsazuresamples">MSDN code gallery</a>.<br />(3) In Visual Studio 2008 or 2010 create the new Windows Azure Cloud Service project.<br />(4) In the pop-up dialog add C# ASP.NET Web Role into the Cloud Service Solution.<br />(5) Compile StorageClient solution that is included in the advanced samples obtained on step (2). From the Web Role add the reference to StorageClient assembly.<br />(alternatively you can include the *.cs files from StorageClient solution to the Web Role project. F.e. I've added them as a link in my test project). <br />(6) Add the reference to System.Data.Services.Client in Web Role project.<br />Steps (7)-(23) are the same as in <a href="http://blogs.msdn.com/jnak/archive/2008/10/28/walkthrough-simple-table-storage.aspx">Table Storage Walkthrough</a>. However step 22(Create Test Storage Tables) is not needed with Windows Azure SDK 1.1.<br />(24) Add several contacts using the form on the default page of the cloud service. We will show the contacts list using ActiveReports.<br />(25) Add the new ActiveReports 6(code-based) File in the Web Role Project(in the root folder). Name it "Contacts.cs". <br />(26) Add two textboxes to the detail section of the report. Set DataField property to "Name"(without quotes) for the 1st textbox. Set DataField property to "Address"(without quotes) for the 2nd textbox. <br />(27) Add the new Web Form in the Web Role Project. Name the new form "ARReportForm.aspx".<br />(28) <a href="http://www.datadynamics.com/Help/ActiveReports6/arWLKWebViewer.html">Add ActiveReports6 web-based report viewer</a> in ARReportForm page.<br />(29) Add the following code to the Page_Load event handler of ARReportForm:<br /><pre style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;"><br />var rpt = <span style="color: #0000ff;">new</span> Contacts();<br />var ds = <span style="color: #0000ff;">new</span> ContactDataSource();<br />rpt.DataSource = (from c <span class="kwrd">in</span> ds.Select() select <span style="color: #0000ff;">new</span> {c.Name, c.Address}).ToArray();<br />rpt.Run(<span style="color: #0000ff;">false</span>);<br />WebViewer1.ClearCachedReport();<br />WebViewer1.Report = rpt;<br /></pre><br />ActiveReports allows you to use the collection of the objects as the data source, so we can use the result that is returned by ContactDataSource.Select method.<br />(30) Set ARReportForm.aspx as the Start Page, run the cloud service and you will see that web-viewer shows the contacts that you added on step (24).<br /><span style="font-weight:bold;">End of walkthrough.</span><br /></font>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com0tag:blogger.com,1999:blog-5306024932265403945.post-7687186103807956032010-04-11T11:56:00.006+07:002010-04-11T13:21:58.622+07:00Tips and tricks: Exporting to CSV using Data Dynamics Reports<font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>General</b></font><br /><font style="font-family:Tahoma;font-size:10pt">This is the first in a series of posts that will highlight small and simple but useful undocumented features of <a href="http://www.datadynamics.com/Products/DDRPT/Overview.aspx">Data Dynamics Reports</a> and <a href="http://www.datadynamics.com/Products/ActiveReports/Overview.aspx">ActiveReports</a>. I have several topics in mind and hope that more ideas about such features come soon. I will start with the answer to question we were recently asked - is that possible to export the report to <a href="http://en.wikipedia.org/wiki/Comma-separated_values">CSV</a> format using Data Dynamics Reports?</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Tip: use Xml Rendering Extension to get CSV output.</b></font><br /><font style="font-family:Tahoma;font-size:10pt">That sounds weird, but it's really not. Let me explain. Data Dynamics Reports allows you to save the data that are shown by a report to XML format. The output XML content does not include the information about report items style, pagination, interactivity, etc., it only includes the data that are grouped, sorted, filtered and displayed in the report's data regions. For example say that a report consists of a simple table that has two columns, the header and the details:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggppW0-ePOpuqqRJulQIo06eSPiT8TIgu9JETaOblhrUn8vEiZAtSoTB3SZtmlBB7SNE_n0KGu3eTt-gWzctk76hEcQNhxyXrTWVHULao8i_0CYKmgNxZ_YWTuTltR11SZJwoky6Njb-aW/s1600/SimpleTable.png"><img style="cursor:pointer; cursor:hand;width: 293px; height: 152px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggppW0-ePOpuqqRJulQIo06eSPiT8TIgu9JETaOblhrUn8vEiZAtSoTB3SZtmlBB7SNE_n0KGu3eTt-gWzctk76hEcQNhxyXrTWVHULao8i_0CYKmgNxZ_YWTuTltR11SZJwoky6Njb-aW/s400/SimpleTable.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5458753912910150306" /></a><br />The report output in the viewer would look like below:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRuKTd4AUI50oGCaXDJRIZVnw2maFMg_KD8OlgDFY57rDvqUWvH8dRr9K73_3Kt0j9mLpgiGMG0bMLSl6gz9vtqZHAtkJl27vfOvtbp709THoCFcYNGpIRJ3hx2J19yShG4oaNgGQRtgFo/s1600/TableOutput.png"><img style="cursor:pointer; cursor:hand;width: 234px; height: 152px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRuKTd4AUI50oGCaXDJRIZVnw2maFMg_KD8OlgDFY57rDvqUWvH8dRr9K73_3Kt0j9mLpgiGMG0bMLSl6gz9vtqZHAtkJl27vfOvtbp709THoCFcYNGpIRJ3hx2J19yShG4oaNgGQRtgFo/s400/TableOutput.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5458754702158867842" /></a><br />But the output that is produced by <a href="http://www.datadynamics.com/Help/ddReports/ddrconXML.html">Xml Rendering Extension</a> looks like:<br /><pre style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;"><br /><span style="color: #0000ff;"><</span><span style="color: #800000;">Report</span> <span style="color: #ff0000;">Name</span><span style="color: #0000ff;">="Ages.rdlx"</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">Table1</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">TextBox2</span><span style="color: #0000ff;">></span>Age<span style="color: #0000ff;"></</span><span style="color: #800000;">TextBox2</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">TextBox1</span><span style="color: #0000ff;">></span>Name<span style="color: #0000ff;"></</span><span style="color: #800000;">TextBox1</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">Detail_Collection</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">Detail</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">TextBox5</span><span style="color: #0000ff;">></span>30<span style="color: #0000ff;"></</span><span style="color: #800000;">TextBox5</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">TextBox4</span><span style="color: #0000ff;">></span>Jon<span style="color: #0000ff;"></</span><span style="color: #800000;">TextBox4</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"></</span><span style="color: #800000;">Detail</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">Detail</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">TextBox5</span><span style="color: #0000ff;">></span>27<span style="color: #0000ff;"></</span><span style="color: #800000;">TextBox5</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">TextBox4</span><span style="color: #0000ff;">></span>Michael<span style="color: #0000ff;"></</span><span style="color: #800000;">TextBox4</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"></</span><span style="color: #800000;">Detail</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">Detail</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">TextBox5</span><span style="color: #0000ff;">></span>32<span style="color: #0000ff;"></</span><span style="color: #800000;">TextBox5</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">TextBox4</span><span style="color: #0000ff;">></span>Bryan<span style="color: #0000ff;"></</span><span style="color: #800000;">TextBox4</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"></</span><span style="color: #800000;">Detail</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">Detail</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">TextBox5</span><span style="color: #0000ff;">></span>29<span style="color: #0000ff;"></</span><span style="color: #800000;">TextBox5</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">TextBox4</span><span style="color: #0000ff;">></span>Stewart<span style="color: #0000ff;"></</span><span style="color: #800000;">TextBox4</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"></</span><span style="color: #800000;">Detail</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"></</span><span style="color: #800000;">Detail_Collection</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"></</span><span style="color: #800000;">Table1</span><span style="color: #0000ff;">></span><br /><span style="color: #0000ff;"></</span><span style="color: #800000;">Report</span><span style="color: #0000ff;">></span></pre><br />The element names in the output XML file can be fine-tuned using the properties on the individual report items, more details can be found on the <a href="http://www.datadynamics.com/Help/ddReports/ddrconXML.html">corresponding help topic</a>. That's all good, but how to get the same data in CSV format? For example:<br />Name,Age<br />Jon,30<br />Michael,27<br />Bryan,32<br />Stewart,29<br />Xml Rendering Extension has XsltStyleSheet setting, you can specify the stylesheet that will be applied to the output XML before producing the resulting document. Therefore you can write the XSLT that transforms XML content to CSV content. It's of course not possible to implement the uniform XSLT for all the reports, but the example for the table-based report where the table has the 1-row header and 1-row details is shown below. It works for any number of columns: <br /></font><br /><pre style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;"><br /><span style="color: #0000ff;"><</span><span style="color: #800000;">xsl:stylesheet</span> <span style="color: #ff0000;">version</span><span style="color: #0000ff;">="1.0"</span> <span style="color: #ff0000;">xmlns:xsl</span><span style="color: #0000ff;">="http://www.w3.org/1999/XSL/Transform"</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">xsl:template</span> <span style="color: #ff0000;">match</span><span style="color: #0000ff;">="/"</span><span style="color: #0000ff;">></span><br /> <span style="color: #008000;"><!--Select the table header content --></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">xsl:for-each</span> <span style="color: #ff0000;">select</span><span style="color: #0000ff;">="Report/Table1/*"</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">xsl:if</span> <span style="color: #ff0000;">test</span><span style="color: #0000ff;">="name(current())!='Detail_Collection'"</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">xsl:if</span> <span style="color: #ff0000;">test</span><span style="color: #0000ff;">="not(position() = 1)"</span><span style="color: #0000ff;">></span>,<span style="color: #0000ff;"></</span><span style="color: #800000;">xsl:if</span><span style="color: #0000ff;">><</span><span style="color: #800000;">xsl:value-of</span> <span style="color: #ff0000;">select</span><span style="color: #0000ff;">="current()"</span> <span style="color: #0000ff;">/></span><br /> <span style="color: #0000ff;"></</span><span style="color: #800000;">xsl:if</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"></</span><span style="color: #800000;">xsl:for-each</span><span style="color: #0000ff;">></span><br /> <span style="color: #008000;"><!--Insert the line break--></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">xsl:text</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"></</span><span style="color: #800000;">xsl:text</span><span style="color: #0000ff;">></span><br /><br /> <span style="color: #008000;"><!--select the table details content --></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">xsl:for-each</span> <span style="color: #ff0000;">select</span><span style="color: #0000ff;">="Report/Table1/Detail_Collection/Detail"</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">xsl:for-each</span> <span style="color: #ff0000;">select</span><span style="color: #0000ff;">="current()/*"</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">xsl:if</span> <span style="color: #ff0000;">test</span><span style="color: #0000ff;">="not(position() = 1)"</span><span style="color: #0000ff;">></span>,<span style="color: #0000ff;"></</span><span style="color: #800000;">xsl:if</span><span style="color: #0000ff;">><</span><span style="color: #800000;">xsl:value-of</span> <span style="color: #ff0000;">select</span><span style="color: #0000ff;">="current()"</span> <span style="color: #0000ff;">/></span><br /> <span style="color: #0000ff;"></</span><span style="color: #800000;">xsl:for-each</span><span style="color: #0000ff;">></span><br /> <span style="color: #008000;"><!--Insert the line break--></span><br /> <span style="color: #0000ff;"><</span><span style="color: #800000;">xsl:text</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"></</span><span style="color: #800000;">xsl:text</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"></</span><span style="color: #800000;">xsl:for-each</span><span style="color: #0000ff;">></span><br /> <span style="color: #0000ff;"></</span><span style="color: #800000;">xsl:template</span><span style="color: #0000ff;">></span><br /><span style="color: #0000ff;"></</span><span style="color: #800000;">xsl:stylesheet</span><span style="color: #0000ff;">></span></pre>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com0tag:blogger.com,1999:blog-5306024932265403945.post-44972321429285356142010-03-14T21:21:00.004+06:002010-03-15T22:13:02.842+06:00Data Dynamics Reports: Show the Data from the Windows Azure Table Storage<font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Preface</b></font><br /><font style="font-family:Tahoma;font-size:10pt">Some time ago I tested <a href="http://www.datadynamics.com/Products/DDRPT/Overview.aspx">Data Dynamics Reports</a> on <a href="http://www.microsoft.com/windowsazure/">Windows Azure</a> platform. I never dealt with Windows Azure before and was happy to learn something new. In particular I've learned the basics of Windows Azure Storage Services. There are 3 storage types in Windows Azure: blobs, queues and tables. I thought about the scenario when a developer wants to visualize the data from Window Azure Table Storage using Data Dynamics Reports. I've found that Data Dynamics Report provides developer with all needed ammunition to achieve that goal, so I thought that it would be worth to write about. </font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Windows Azure Table Storage</b></font><br /><font style="font-family:Tahoma;font-size:10pt">Windows Azure Table Storage differs from the tables in a relational database. Table storage is object-oriented and saves the entities and the entity properties. The details of table storage is not the subject of this post. I believe that the best way to show how Data Dynamics Reports can be used with the table storage is going through the live example. This walkthrough is based on <a href="http://blogs.msdn.com/jnak/archive/2008/10/28/walkthrough-simple-table-storage.aspx">the post</a> in <a href="http://blogs.msdn.com/jnak/default.aspx">"Cloudy in Seattle" blog</a>. However, that blog post sample uses Windows Azure SDK 1.0 and I used the newer version 1.1. A few things was changed in version 1.1, I highlighted them later in this post.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Walkthrough</b></font><br /><font style="font-family:Tahoma;font-size:10pt">This walkthrough is totally based on <a href="http://blogs.msdn.com/jnak/archive/2008/10/28/walkthrough-simple-table-storage.aspx">"Windows Azure Walkthrough: Table Storage"</a>. I just aligned it with the changes in Windows Azure SDK v1.1 and added the steps for show the data using Data Dynamics Reports.<br />(1) <a href="http://www.microsoft.com/windowsazure/getstarted/">Get started with Windows Azure</a> - install the prerequisites and SDK v1.1. Install the <a href="http://www.datadynamics.com/Products/DDRPT/Releases.aspx">latest release of Data Dynamics Reports</a>.<br />(2) Download and extract Windows Azure Additional Samples from <a href="http://code.msdn.microsoft.com/windowsazuresamples">MSDN code gallery</a>.<br />(3) In Visual Studio 2008 or 2010 create the new Windows Azure Cloud Service project.<br />(4) In the pop-up dialog add C# ASP.NET Web Role into the Cloud Service Solution.<br />(5) Compile StorageClient solution that is included in the advanced samples obtained on step (2). From the Web Role add the reference to StorageClient assembly.<br />(alternatively you can include the *.cs files from StorageClient solution to the Web Role project. F.e. I've added them as a link in my test project). <br />(6) Add the reference to System.Data.Services.Client in Web Role project.<br />Steps (7)-(23) are the same as in <a href="http://blogs.msdn.com/jnak/archive/2008/10/28/walkthrough-simple-table-storage.aspx">Table Storage Walkthrough</a>. However step 22(Create Test Storage Tables) is not needed with Windows Azure SDK 1.1.<br />(24) Add several contacts using the form on the default page of the cloud service. We will show the contacts list using Data Dynamics Reports.<br />(25) Add the new Data Dynamics Reports Report Item in the Web Role Project(in the root folder). Name it "Contacts.rdlx". Set Build Action property of Contacts.rdlx file to "Content".<br />(26) Using the <a href="http://www.datadynamics.com/Help/ddReports/ddrdoriDataView.html">Report Data Explorer</a>, <a href="http://www.datadynamics.com/Help/ddReports/ddroriReportDataSourceSmartPanel.html">add the new Data Source</a> in the report. On the <a href="http://www.datadynamics.com/Help/ddReports/ddrdconDataSourceGeneralTab.html">General Page</a> set the Data Source Type to <a href="http://www.datadynamics.com/Help/ddReports/ddrconDataSetAndObjectDataSource.html">Object Provider</a>.<br />(27) <a href="http://www.datadynamics.com/Help/ddReports/ddrdoriDataset.html">Add the new Data Set</a> to the Data Source that is created on step (26). Leave the <a href="http://www.datadynamics.com/Help/ddReports/ddrdconDatasetQueryTab.html">data set query</a> empty. On the <a href="http://www.datadynamics.com/Help/ddReports/ddrdconDatasetFieldsTab.html">Fields Page</a> of the Data Set add two fields "Name" and "Address".<br />(28) Add the <a href="http://www.datadynamics.com/Help/ddReports/ddrconTable.html">Table</a> to the report, bind the table to the Data Set that is created on step (27). Adjust the table so that it contains 2 columns and the 1st column shows Name field and the 2nd column shows Address field.<br />(29) Add the new Web Form in the Web Role Project. Name the new form "ReportForm.aspx".<br />(30) <a href="http://www.datadynamics.com/Help/ddReports/ddrwlkWebReportViewer.html">Add Data Dynamics Reports Web Viewer</a> to ReportForm page.<br />(31) Add the following code to the Page_Load event handler of ReportForm:<br /><div style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;><br /><span style="color: #0000ff;">const string</span> rptPath = <span style="color: #006080;">"~/Contacts.rdlx"</span>;<br /><span style="color: #0000ff;">string</span> rptPath2 = Server.MapPath(rptPath);<br /><span style="color: #0000ff;">var</span> def = <span style="color: #0000ff;">new</span> ReportDefinition(<span style="color: #0000ff;">new</span> FileInfo(rptPath2));<br /><span style="color: #0000ff;">var</span> runtime = <span style="color: #0000ff;">new</span> ReportRuntime(def);<br />runtime.LocateDataSource += (s, args) =><br />{<br /> <span style="color: #0000ff;">var</span> ds = <span style="color: #0000ff;">new</span> ContactDataSource();<br /> args.Data = ds.Select();<br />};<br />WebReportViewer1.SetReport(runtime);<br /></div><br />So, we used Object Data Provider for the report data source. Object Data Provider accepts the objects that implement IEnumerable interface. ContactDataSource.Select method returns the results of the query to the TableStorage as IEnumerable<ContactModel> instance and we can use it for the report data source.<br />(32) Set ReportForm.aspx as the Start Page, run the cloud service and you will see that web-viewer shows the contacts that you added on step (24).<br /><span style="font-weight:bold;">End of walkthrough.</span><br /></font>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com0tag:blogger.com,1999:blog-5306024932265403945.post-59508909638879517182010-02-14T18:59:00.005+06:002010-02-14T21:30:01.797+06:00Interaction between the Report and the Hosting application, Email Rendering Extension and more<font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Preface</b></font><br /><font style="font-family:Tahoma;font-size:10pt">I was pretty busy during past week and did not get the good ideas for the new post. Therefore I am going to write about two fairly new features of <a href="http://www.datadynamics.com/Products/DDRPT/Overview.aspx">Data Dynamics Reports</a>. They are Action event of <a href="http://www.datadynamics.com/Help/ddReports/ddrconReportPreview.html">Windows Forms Viewer</a> and <a href="http://www.datadynamics.com/Help/ddReports/ddrconWebViewer.html">WebViewer</a> and Email Rendering Extension. They are not well-documented yet, therefore this post will be probably helpful for someone.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Action event</b></font><br /><font style="font-family:Tahoma;font-size:10pt">Data Dynamics Reports has the great interactivity capabilities. It supports the <a href="http://www.datadynamics.com/Help/ddReports/ddrconHyperlinks.html">hyperlinks</a>, <a href="http://www.datadynamics.com/Help/ddReports/ddrconDrillThrough.html">drill-through links</a>, <a href="http://www.datadynamics.com/Help/ddReports/ddrconDrillDownReports.html">drill-down links</a>, interactive sorting, <a href="http://www.datadynamics.com/Help/ddReports/ddrconBookmarks.html">bookmarks</a> and the <a href="http://www.datadynamics.com/Help/ddReports/ddrconDocumentMaps.html">document maps</a>. However, sometimes <a href="http://www.datadynamics.com/forums/125122/ShowPost.aspx">developer needs</a> a custom type of interactivity. For instance - the report shows the list of employees, if a user clicks on the employee name in the report, then e-mail of employee is added in the internal list in the hosting application. A user selects a bunch of employees, closes the report and clicks "Send" button in the hosting application. The e-mail with the subject "You are fired" is sent to each employee from the list. Some time ago, it was not possible to implement such scenario using Data Dynamics Reports. But the fabulous product team went ahead and implemented the new feature that is called "Action event". Windows Forms Report Viewer and Web Report Viewer now have Action event. It is raised when a user clicks on the hyperlink, bookmark link or drill-through link in the report that is displayed in the viewer. In the handler of Action event developer can perform the custom steps and cancel the further action processing. Here is the sample of code: </font><br /><div style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;><br /><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">partial</span> <span style="color: #0000ff;">class</span> _Default : System.Web.UI.Page <br />{<br /> <span style="color: #0000ff;">internal</span> List<<span style="color: #0000ff;">string</span>> _emailsList = <span style="color: #0000ff;">new</span> List<<span style="color: #0000ff;">string</span>>();<br /> <br /> <span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">void</span> Page_Load(<span style="color: #0000ff;">object</span> sender, EventArgs e)<br /> {<br /> WebReportViewer1.Action += WebReportViewer1_Action;<br /> }<br /><br /> <span style="color: #0000ff;">void</span> WebReportViewer1_Action(<span style="color: #0000ff;">object</span> sender, ActionEventArgs e)<br /> {<br /> <span style="color: #0000ff;">if</span>(e.Action.ActionType == ActionType.HyperLink)<br /> {<br /> _emailsList.Add(e.Action.HyperLink);<br /> e.Cancel = <span style="color: #0000ff;">true</span>;<br /> }<br /> e.Cancel = <span style="color: #0000ff;">false</span>;<br /> }<br />}<br /></div><br /><font style="font-family:Tahoma;font-size:10pt">ActionEventArgs instance that is passed in Action event handler contains all the needed information: the type of Action and the value of the hyperlink, drill-through link or bookmark link. The most amazing fact about Action event is the uniform way it is implemented. It works for Windows Forms Viewer, Web Report Viewer-HTML mode and Web Report Viewer-<span style="font-weight:bold;">PDF mode</span>. In all cases developer just needs to add the handler for Action event.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Email Rendering Extension</b></font><br /><font style="font-family:Tahoma;font-size:10pt">Email Rendering Extension is the new rendering engine that allows to generate the report output which is compatible with the most popular e-mail clients. The clients with which we tested Email Rendering Extensions are:<br /><ul><br /><li>Outlook 2007</li><br /><li>Outlook 2003</li><br /><li>Gmail</li><br /><li>Yahoo</li><br /><li>Hotmail</li><br /><li>Thunderbird</li><br /></ul><br />Email Rendering Extension supports two modes - it can write the output to the file or memory stream and it can build the instance of <a href="http://msdn.microsoft.com/en-us/library/system.net.mail.mailmessage.aspx">System.Net.Mail.MailMessage</a> which is available via the pubic property. The MailMessage instance that is generated by Email Rendering Extension contains <a href="http://msdn.microsoft.com/en-us/library/system.net.mail.mailmessage.alternateviews.aspx">the html view</a> of the message and all the attachments, i.e. images, if any. Here is the sample of the code which sends the report output to the list of recipients, it continues the code that is shown above:</font><br /><div style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;><br /><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">partial</span> <span style="color: #0000ff;">class</span> _Default : System.Web.UI.Page <br />{<br /> <span style="color: #0000ff;">internal</span> List<<span style="color: #0000ff;">string</span>> _emailsList = <span style="color: #0000ff;">new</span> List<<span style="color: #0000ff;">string</span>>();<br /> <br /> <span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">void</span> btnSend_Click(<span style="color: #0000ff;">object</span> sender, EventArgs e)<br /> {<br /> <span style="color: #0000ff;">var</span> re = <span style="color: #0000ff;">new</span> EmailRenderingExtension();<br /> <span style="color: #0000ff;">var</span> def = <span style="color: #0000ff;">new</span> ReportDefinition(<span style="color: #0000ff;">new</span> FileInfo(Server.MapPath(<span style="color: #006080;">"~/Email.rdlx"</span>)));<br /> <span style="color: #0000ff;">var</span> runtime = <span style="color: #0000ff;">new</span> ReportRuntime(def);<br /> runtime.Render(re, <span style="color: #0000ff;">null</span>);<br /> <span style="color: #0000ff;">var</span> emailMessage = re.MailMessage;<br /> emailMessage.Subject = <span style="color: #006080;">"You are fired"</span>; <br /> <span style="color: #0000ff;">foreach</span>(<span style="color: #0000ff;">string</span> email <span style="color: #0000ff;">in</span> _emailsList)<br /> emailMessage.To.Add(email);<br /> <span style="color: #0000ff;">var</span> fromAddress = <span style="color: #0000ff;">new</span> MailAddress(<span style="color: #006080;">"boss@company.com"</span>,<span style="color: #006080;">"Big Boss"</span>);<br /> emailMessage.Sender = fromAddress;<br /> emailMessage.From = fromAddress;<br /> <span style="color: #0000ff;">var</span> smtp = <span style="color: #0000ff;">new</span> SmtpClient(<span style="color: #006080;">"127.0.0.1"</span>, 25);<br /> smtp.Send(emailMessage);<br /> }<br />}<br /></div><br /><font style="font-family:Tahoma;font-size:10pt">In this code Email Rendering Extension does not render the report to the file or memory stream. MailMessage property is used instead.</font>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com0tag:blogger.com,1999:blog-5306024932265403945.post-69431015027368148652010-02-07T18:48:00.004+06:002010-02-07T21:59:37.516+06:00A few thoughts about no-touch printing in ActiveReports6<font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Preface</b></font><br /><font style="font-family:Tahoma;font-size:10pt">I am not sure what is the proper term for the functionality that allows to print a document with no user interaction. In this post I am using "no-touch printing" term. For instance: Every morning Jon Smith turns on his computer at the office and runs his favorite internet browser. The browser opens the start page which is the company web-site. The start page of the company web-site indicates that Jon Smith has logged in and prints the daily schedule on the default printer that is set up on Jon's computer. Let's see how we can implement such scenario using ActiveReports6.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>ActiveX Viewer And Flash Viewer.</b></font><br /><font style="font-family:Tahoma;font-size:10pt"><a href="http://www.datadynamics.com/Products/ProductFeatures.aspx?Product=AR2&Topic=ActiveX%20Viewer">ActiveX Viewer</a> was introduced in the <a href="http://www.datadynamics.com/Products/ProductOverview.aspx?Product=AR2">COM version</a> of the product. ActiveReports was growing up, .NET framework became the product environment, but ActiveX Viewer never was dead in the water, and with good reason! ActiveX Viewer provides developer with the rich capabilities of displaying and printing the reports on the web. For example it's pretty easy to implement no-touch printing on the web with ActiveX Viewer. The code should load the report in the viewer, then wait until the loading is finished and then call PrintReport method. The <a href="http://www.datadynamics.com/forums/12/ShowForum.aspx">knowledge base</a> of ActiveReports has several articles that show the sample of such code.<br />Of course the main disadvantage of ActiveX Viewer is it's ActiveX component. ActiveX components officially operate only with IE and Windows. In our days <a href="http://www.netmarketshare.com/report.aspx?qprid=0&qptimeframe=M&qpsp=132">the usage share</a> of IE is only ~60%. Developers need more uniform technology that allows displaying and printing reports on the web. In ActiveReports6 ActiveX viewer is not supported but <a href="http://www.datadynamics.com/Help/ActiveReports6/arWLKFlashViewer.html">Flash Viewer</a> is introduced instead.<br />Flash Viewer operates with any browser and any OS where the flash player is installed.<br />The bad news are Flash Viewer <a href="http://www.datadynamics.com/forums/130473/ShowPost.aspx">does not support no-touch printing</a>.<br />So, it seems that there are no ways to implement no-touch printing on the web with ActiveReports6? Not exactly!<br /></font><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Turn around.</b></font><br /><font style="font-family:Tahoma;font-size:10pt">To display PDF documents in browser <a href="http://get.adobe.com/reader/">Adobe Acrobat Reader</a> includes the Acrobat ActiveX control for Internet Explorer and the Adobe PDF Plug-In For Firefox and Netscape. ActiveX control or FF plug-in can be hosted by the HTML page and a PDF document can be loaded and printed using Javascript or Visual Basic code of that page. I am confident that no-touch printing is possible to implement with Acrobat ActiveX control and I believe that it's possible with Adobe FF plug-in as well. In other hand ActiveReports6 includes the <a href="http://www.datadynamics.com/Help/ActiveReports6/arHOWUseHTTPHandlersWithWebForms.html">RPX handler</a> which can return the report is saved in PDF format...No more words! Here is sample of code which performs no-touch printing of the report using Acrobat ActiveX control: </font><br /><div style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;><br /><span style="color:blue"><</span><span style="color: #800000;">html</span><span style="color:blue">></span><br /><span style="color:blue"><</span><span style="color: #800000;">body</span> <span style="color: red;">onload</span><span style="color:blue">="window.setTimeout('em.PrintAll();', 5000);"</span><span style="color:blue">></span><br /><span style="color:blue"><</span><span style="color: #800000;">div</span> <span style="color: red;">id</span><span style="color:blue">="PdfContainer"</span><span style="color:blue">></span><br /><span style="color:blue"><</span><span style="color: #800000;">span</span> <span style="color: red;">style</span><span style="color:blue">="font-size: large;"</span><span style="color:blue">></span>Please wait for a few seconds and the printing will be starting.<span style="color:blue"></</span><span style="color: #800000;">span</span><span style="color:blue">></span><br /><span style="color:blue"><</span><span style="color: #800000;">embed</span> <span style="color: red;">id</span><span style="color:blue">="em"</span> <span style="color: red;">width</span><span style="color:blue">="0"</span> <span style="color: red;">height</span><span style="color:blue">="0"</span> <span style="color: red;">src</span><span style="color:blue">="HelloWorld.rpx?OutputFormat=PDF"</span> <span style="color:blue">/></span><br /><span style="color:blue"></</span><span style="color: #800000;">div</span><span style="color:blue">></span><br /><span style="color:blue"></</span><span style="color: #800000;">body</span><span style="color:blue">></span><br /><span style="color:blue"></</span><span style="color: #800000;">html</span><span style="color:blue">></span><br /></div><br /><font style="font-family:Tahoma;font-size:10pt">The code uses <a href="http://www.w3schools.com/html5/tag_embed.asp">EMBED tag</a> to host the PDF document which is returned by RPX handler. PrintAll method prints the entire document without displaying a user dialog box. There are two issues with that code. First of all, it uses the timeout approach to wait until the document is loaded in PDF viewer. I think it's possible to intercept the event which is raised by PDF control when the document loading is completed, I just don't know the exact way to do that. The second issue is the warning which appears before printing starts:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkYRw2VtFWI4-vbFY3mgZLl7SfBXDMVVvBKktuuQjg3mnKStQ_7FrYEhmUnraWR-rp8QbJHfvLanAhgr5TeHL3Lao1I8O8n6MheoEunHzag0j-codYwNGOYQgrPugwbz1hSAnecz6pRhN6/s1600-h/Warning.PNG"><img style="cursor:pointer; cursor:hand;width: 400px; height: 142px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkYRw2VtFWI4-vbFY3mgZLl7SfBXDMVVvBKktuuQjg3mnKStQ_7FrYEhmUnraWR-rp8QbJHfvLanAhgr5TeHL3Lao1I8O8n6MheoEunHzag0j-codYwNGOYQgrPugwbz1hSAnecz6pRhN6/s400/Warning.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5435520429770338434" /></a><br />Once "Don't show this message again" checkbox is unchecked, the code provides the no-touch printing, really.<br /></font><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Great Silver Hope</b></font><br /><font style="font-family:Tahoma;font-size:10pt">Eventually we will add the Silverlight-based Reports Viewer for ActiveReports. At the moment the most recent version of Silverlight is <a href="http://silverlight.net/getstarted/silverlight-4-beta/">v.4 Beta 2</a> and it's new features list includes:<br /><span style="font-style:italic;">Comprehensive printing support enabling hardcopy reports and documents as well as a virtual print view, independent of screen content</span>. <br />Unfortunately, that "comprehensive printing support" does not include no-touch printing. The great review of Silverligh 4 printing is available <a href="http://wildermuth.com/2009/11/27/Silverlight_4_s_Printing_Support">here</a>.<br />Perhaps the final version of Silverlight 4 or 5 will support no-touch printing. Then we will add the Silverlight-based Reports Viewer and no-touch printing will be fully supported in ActiveReports. That's what I called "Great Silver Hope":)<br /></font>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com2tag:blogger.com,1999:blog-5306024932265403945.post-38431196149529996472010-01-31T15:00:00.009+06:002010-02-01T23:50:09.691+06:00The fresh glance at using ActiveReports 6 in ASP.NET MVC.<font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Preface</b></font><br /><font style="font-family:Tahoma;font-size:10pt">I am a big fan of <a href="http://www.asp.net/mvc/">ASP.NET MVC</a>. I never liked developing of the web-applications using CGI, PHP, ASP, JSP and finally ASP.NET. Remember "The reason most people want to program for the web is that they're not smart enough to do anything else"<a href="http://www.codinghorror.com/blog/archives/001296.html"> discussion</a>? I agree with Michael Braude. In other hands ASP.NET MVC provides developers with the solid framework with which you work with <a href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller">Model-View-Controller design pattern</a>, use well-known practices to follow <a href="http://en.wikipedia.org/wiki/DRY">DRY principle</a>, extend the native functionality to achieve the specific requirements, etc. It's just beautiful. Indeed I was excited about using <a href="http://www.datadynamics.com/Products/ActiveReports/Overview.aspx">ActiveReports</a> and <a href="http://www.datadynamics.com/Products/DDRPT/Overview.aspx">Data Dynamics Reports</a> in ASP.NET MVC applications. We published the <a href="http://jon-pilgrim.blogspot.com/2009/03/using-activereports-webviewer-with.html">screencast</a> which shows how to use the <a href="http://www.datadynamics.com/Help/ActiveReports6/arGETWebViewer.html">ActiveReports WebViewer</a> in ASP.NET MVC application, but this way is not essential for ASP.NET MVC framework. In this article I am going to demonstrate how to create ActiveReports6 WebViewer control for ASP.NET MVC. </font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>ASP.NET MVC and server-side controls.</b></font><br /><font style="font-family:Tahoma;font-size:10pt">The most annoying thing about ASP.NET MVC is it's not designed for use with the ASP.NET server-side controls. <a href="http://jeffhandley.com/archive/2008/02/24/custom-controls-everywhere-and-asp.net-mvc-part-1.aspx">Custom Controls Everywhere and ASP.NET MVC</a> totally covers that subject. Of course this article was written two years ago, but the main thought is still truth. ASP.NET MVC provides developers with the <a href="http://msdn.microsoft.com/en-us/library/dd410596.aspx">bunch of the helper methods</a> which allow to create the UI and all the controls which you can create are client-side. The typical ASP.NET MVC approach to render the UI is shown <a href="http://weblogs.asp.net/blogs/scottgu/image_thumb_43169D8D.png">here</a>. Of course it <span style="font-style:italic;">is</span> possible to use the server-side control on ASP.NET MVC applications. For example, we made sure that both of ActiveReports and Data Dynamics Reports web-viewer controls which are server-side ASP.NET controls work fine against the ASP.NET MVC framework. But the way which should be used to get them working is not essential...Imagine how it would be nice to just write the single line of code in <a href="http://msdn.microsoft.com/en-us/library/dd410123.aspx">ASP.NET MVC View</a> page:</font><br /><div style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;><br /><%=Html.WebViewerFor(<span style="color: #006080;">"reportViewer"</span>, Model, <span style="color: #0000ff;">new</span> {width=<span style="color: #006080;">"100%"</span>, height=<span style="color: #006080;">"100%"</span>}) %><br /></div><br /><font style="font-family:Tahoma;font-size:10pt">to get web-viewer working. Well, this is what we will achieve at the end of this article.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>ActiveReports 6 Flash Viewer Secrets.</b></font><br /><font style="font-family:Tahoma;font-size:10pt">One of the cool new features of ActiveReports 6 is the new <a href="http://www.datadynamics.com/Help/ActiveReports6/Images/FlashViewerOptionsCallouts.png">Flash-based web-viewer</a>. Flash-based viewer loads <a href="http://www.datadynamics.com/Help/ActiveReports6/arHOWSaveandLoadReportFiles.html">RDF files</a> and displays the report content. There is one problem about Flash Viewer though. The <a href="http://www.datadynamics.com/Help/ActiveReports6/arWLKCustomFlashViewer.html">public API</a> allows loading the report and customizing the UI using the server-side helpers only. We recently got <a href="http://www.datadynamics.com/forums/130558/ShowPost.aspx">a bit of criticism</a> regarding the first problem and I provided the work around the problem. This turn around allows to render the content which displays flash viewer and specifies the report to show in the viewer and all those actions are performed on client-side. This Flash Viewer "secret" is the base for ActiveReports 6 ASP.NET MVC control. </font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>XML-based reports and RPX handler.</b></font><br /><font style="font-family:Tahoma;font-size:10pt">Here I should note that all the further discussion and code suppose that the reports which are used in web-application are <a href="http://www.datadynamics.com/Help/ActiveReports6/arActiveReportsTemplates.html">xml-based</a> and <a href="http://www.datadynamics.com/Help/ActiveReports6/arHOWUseHTTPHandlersWithWebForms.html">RPX handler</a> is set up. RPX handler provides the comfortable way to pass the report parameters and return the report is saved in RDF format. For example - there is xml-based Customers.rpx report which is saved in the root of my web-application. This report shows the list of the customers from the certain country. The country is specified via the report parameter. RPX HTTP handler allows to use the following URL to return the list of British customers in RDF format: http://<server url>/Customers.rpx?Country=Britain&OutputFormat=Rdf3 </font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Creating the View Model for Flash Viewer.</b></font><br /><font style="font-family:Tahoma;font-size:10pt">The UI rendering in ASP.NET MVC deals with the Models and <a href="http://www.asp.net/(S(pdfrohu0ajmwt445fanvj2r3))/learn/mvc/tutorial-04-cs.aspx">Views</a>. The Model is the instance of some class which contains all the information which is needed to render the UI. For example, the list of the Orders is passed in the View and it renders the UI which shows HTML table where each row displays the Order details. Let's compose the class which encapsulates all the information which is needed for Flash Viewer in order to show the report. As I mentioned before, Flash Viewer accepts the RDF documents. To build the URL which returns the RDF document using RPX HTTP Handler we need to know the report name and the parameters values. So, the Flash Viewer View Model class is simple: </font><br /><div style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;><br /><span style="color: #0000ff;">public class</span> ReportViewModel<br />{<br /> <span style="color: #0000ff;">public</span> ReportViewModel()<br /> {<br /> ReportParameters = <span style="color: #0000ff;">new</span> Dictionary<string, object>();<br /> }<br /> <span style="color: #0000ff;">public string</span> ReportName { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span>; }<br /> <span style="color: #0000ff;">public</span> Dictionary<<span style="color: #0000ff;">string</span>, <span style="color: #0000ff;">object</span>> ReportParameters { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">private set</span>; }<br />}<br /></div><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Implementation of the HTML Helper for Flash Viewer Rendering.</b></font><br /><font style="font-family:Tahoma;font-size:10pt">The HTML Rendering Helper in ASP.NET MVC is the extension method for <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.htmlhelper.aspx">System.Web.Mvc.HtmlHelper class</a>. This method should accept the instance of ReportViewModel class and other parameters, the code explains it better:</font><br /><div style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;><br /><span style="color: #0000ff;">public static class</span> FlashViewerExtensions<br />{<br /> <span style="color: #0000ff;">public static string</span> FlashViewerFor(<span style="color: #0000ff;">this</span> HtmlHelper htmlHelper, string name, ReportViewModel model)<br /> {<br /> <span style="color: #0000ff;">return</span> FlashViewerFor(htmlHelper, name, model, null);<br /> }<br /> <br /> <span style="color: #0000ff;">public static string</span> FlashViewerFor(<span style="color: #0000ff;">this</span> HtmlHelper htmlHelper, string name, ReportViewModel model, object htmlAttributes)<br /> {<br /> <span style="color: #0000ff;">var</span> tagBuilder = <span style="color: #0000ff;">new</span> TagBuilder(<span style="color: #006080;">"object"</span>);<br /> tagBuilder.MergeAttribute(<span style="color: #006080;">"type"</span>, <span style="color: #006080;">"application/x-shockwave-flash"</span>);<br /> tagBuilder.MergeAttribute(<span style="color: #006080;">"id"</span>, name);<br /> <span style="color: #008000;">// the following attribute is needed for non-IE browsers.</span><br /> tagBuilder.MergeAttribute(<span style="color: #006080;">"data"</span>, <span style="color: #006080;">"/ActiveReports.FlashViewer.swf"</span>);<br /> if(htmlAttributes!=null)<br />  {<br /> IDictionary<string, object> actualAttributes = <span style="color: #0000ff;">new</span> RouteValueDictionary(htmlAttributes);<br /> <span style="color: #0000ff;">foreach</span>(<span style="color: #0000ff;">var</span> key <span style="color: #0000ff;">in</span> actualAttributes.Keys)<br /> {<br /> tagBuilder.MergeAttribute(key, htmlHelper.Encode(actualAttributes[key]));<br /> }<br /> }<br /> <span style="color: #0000ff;">var</span> innerContent = <span style="color: #0000ff;">new</span> StringBuilder();<br /> innerContent.AppendLine(MovieParameter);<br /> innerContent.AppendLine(GetFlashVarsParameter(model, htmlHelper));<br /> tagBuilder.InnerHtml = innerContent.ToString();<br /> <span style="color: #0000ff;">return</span> tagBuilder.ToString(TagRenderMode.Normal);<br /> }<br /> <br /> <span style="color: #0000ff;">private static string</span> MovieParameter<br /> {<br /> <span style="color: #0000ff;">get</span><br /> {<br /> <span style="color: #0000ff;">if</span>(_movieParameter == <span style="color: #0000ff;">null</span>)<br /> {<br /> <span style="color: #0000ff;">var</span> tagBuilder = <span style="color: #0000ff;">new</span> TagBuilder(<span style="color: #006080;">"param"</span>);<br /> tagBuilder.MergeAttribute(<span style="color: #006080;">"name"</span>, <span style="color: #006080;">"movie"</span>);<br /> tagBuilder.MergeAttribute(<span style="color: #006080;">"value"</span>, <span style="color: #006080;">"/ActiveReports.FlashViewer.swf"</span>);<br /> _movieParameter = tagBuilder.ToString(TagRenderMode.SelfClosing);<br /> }<br /> <span style="color: #0000ff;">return</span> _movieParameter;<br /> }<br /> }<span style="color: #0000ff;">private static string</span> _movieParameter;<br /><br /> <span style="color: #0000ff;">private static string</span> GetFlashVarsParameter(ReportViewModel reportViewModel, HtmlHelper htmlHelper)<br /> {<br /> <span style="color: #0000ff;">var</span> tagBuilder = <span style="color: #0000ff;">new</span> TagBuilder(<span style="color: #006080;">"param"</span>);<br /> tagBuilder.MergeAttribute(<span style="color: #006080;">"name"</span>, <span style="color: #006080;">"FlashVars"</span>);<br /> string url = string.Format(<span style="color: #006080;">"URL={0}.rpx?OutputFormat=Rdf2"</span>, reportViewModel.ReportName);<br /> <span style="color: #0000ff;">foreach</span>(string key <span style="color: #0000ff;">in</span> reportViewModel.ReportParameters.Keys)<br /> {<br /> url += string.Format(<span style="color: #006080;">"&{0}={1}"</span>, key, reportViewModel.ReportParameters[key]);<br /> }<br /> tagBuilder.MergeAttribute(<span style="color: #006080;">"value"</span>, url);<br /> string ret= tagBuilder.ToString(TagRenderMode.SelfClosing);<br /> <span style="color: #0000ff;">return</span> ret.Replace(<span style="color: #006080;">"&amp;"</span>, <span style="color: #006080;">"&"</span>);<br /> }<br />}<br /></div><br /><font style="font-family:Tahoma;font-size:10pt">That's it! MovieParameter property returns <span style="color: #006080;"><param name="movie" value="/ActiveReports.FlashViewer.swf" /></span> tag, the code supposes that ActiveReports.FlashViewer.swf seats in the root folder of the web-site. GetFlashVarsParameter method returns <span style="color: #006080;"><param name="FlashVars" value="URL=<span style="font-style:italic;">url of the report</span>" /></span> tag, it's built using the report name and the report parameters collection which are passed in the public FlashViewerFor methods. FlashViewerFor methods build <object> tag which would be displayed <a href="https://developer.mozilla.org/en/Using_the_Right_Markup_to_Invoke_Plugins">by any type of browser</a>. The code uses <a href="http://www.asp.net/(S(pdfrohu0ajmwt445fanvj2r3))/learn/mvc/tutorial-35-cs.aspx">System.Web.Mvc.TagBuilder</a> class which is <a href="http://www.asp.net/(S(pdfrohu0ajmwt445fanvj2r3))/learn/mvc/tutorial-35-cs.aspx">well-known practice</a>.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>The sample of usage.</b></font><br /><font style="font-family:Tahoma;font-size:10pt">Here is the code of the <a href="http://www.asp.net/(S(pdfrohu0ajmwt445fanvj2r3))/learn/mvc/tutorial-34-cs.aspx">ASP.NET MVC Action</a> which creates the instance of ReportViewModel class, passes that instance to the ASP.NET MVC View and returns the result:</font><br /><div style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;><br /><span style="color: #0000ff;">public</span> ActionResult Customers()<br />{<br /> <span style="color: #0000ff;">var</span> model = <span style="color: #0000ff;">new</span> ReportViewModel { ReportName = <span style="color: #006080;">"/Reports/Customers"</span> };<br /> return View(<span style="color: #006080;">"CustomersReport"</span>, model);<br />}<br /></div><br /><font style="font-family:Tahoma;font-size:10pt">..and the code of "CustomersReport" View:</font><br /><div style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;><br /><%@ Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage<ReportViewModel>" %><br /><%@ Import Namespace="EmptyMvcApplication.Controllers" %><br /><body><br /><% =Html.FlashViewerFor("reportViewer", Model, new {width="100%", height="500"}) %><br /></body><br /></div><br /><font style="font-family:Tahoma;font-size:10pt">Now, the Customers action of some controller returns the page which hosts flash viewer which shows Customers report.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Finally...</b></font><br /><font style="font-family:Tahoma;font-size:10pt">ASP.NET MVC allows developer to feel like the real developer during the creation of web-based applications. The sample of the extension which is shown in this article is just a little piece of the functionality which is available with ASP.NET MVC.</font>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com4tag:blogger.com,1999:blog-5306024932265403945.post-23399595024640487612010-01-24T20:59:00.003+06:002010-01-24T22:59:21.360+06:00ActiveReports6 : Viewer ToolBar Secrets.<font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Preface</b></font><br /><font style="font-family:Tahoma;font-size:10pt">One of the cool <a href="http://www.datadynamics.com/Products/ActiveReports/WhatsNew.aspx">new features</a> of <a href="http://www.datadynamics.com/Products/ActiveReports/Overview.aspx">ActiveReports6</a> is the <a href="http://www.datadynamics.com/Help/ActiveReports6/arHOWAddDesignerToolStrips.html">updated End User Designer toolbar architecture</a>. Now the <a href="http://www.datadynamics.com/Help/ActiveReports6/ActiveReports.Design6~DataDynamics.ActiveReports.Design.Designer~CreateToolStrips.html">public API</a> exposes the methods which allow to get the designer's toolbar groups and they are <a href="http://msdn.microsoft.com/en-us/library/5daaw6hf.aspx">ToolStrips</a>. Which opens the wide capabilities of the toolbar customization. That is fine but the question which <a href="http://www.datadynamics.com/forums/130212/ShowPost.aspx">we recently got</a> from the clients is "What about ActiveReports6 Windows Viewer toolbar?". The way to customize the viewer toolbar seems to be unchangeable since from ActiveReports for .NET 1.0 times! ActiveReports still allows to customize the viewer toolbar using the <a href="http://www.datadynamics.com/Help/ActiveReports6/ActiveReports.Viewer6~DataDynamics.ActiveReports.Toolbar_namespace.html">"Toolbar API"</a> only. Toolbar API is not the best solution ever, it is pretty limited. Fortunately a bit of digging around ActiveReporrs6 viewer internals can provide us with more comfortable way of toolbar customization. </font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Viewer Toolbar is actually ToolStrip!</b></font><br /><font style="font-family:Tahoma;font-size:10pt">Let's see which child controls are hosted by ActiveReports6 Viewer control. Here is the simple code which performs that:</font><br /><div style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;><br /><span style="color: #0000ff;">var</span> viewer = <span style="color: #0000ff;">new</span> DataDynamics.ActiveReports.Viewer.Viewer();<br /><span style="color: #0000ff;">foreach</span>(Control child <span style="color: #0000ff;">in</span> viewer.Controls)<br /> Debug.WriteLine(<span style="color: #0000ff;">string</span>.Format(<span style="color: #006080;">"name:{0}, type{1}"</span>, child.Name, child.GetType()));<br /></div><br /><font style="font-family:Tahoma;font-size:10pt">That code emits the following output:<br /><br />name:, type#op.#7s<br />name:tocSplitter, typeSystem.Windows.Forms.Splitter<br />name:TableOfContents, typeDataDynamics.ActiveReports.Viewer.TableOfContents<br />name:, typeSystem.Windows.Forms.ToolStrip<br /><br />The first control is one which shows the report pages, the third control is one which shows the TOC, the second control is the separator between the 1st and 3rd controls and 4th control is...yes, that is viewer toolbar! In ActiveReports6 the Windows Viewer toolbar is internally implemented using ToolStrip API. Cool, let's write the simple <a href="http://msdn.microsoft.com/en-us/library/bb383977.aspx">extension method</a> which would provide us with access to viewer's Toolbar which is the ToolStrip:</font><br /><div style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;><br /><span style="color: #0000ff;">public static class</span> ViewerHelper<br />{<br /> <span style="color: #0000ff;">public static</span> ToolStrip CreateToolStrip(<span style="color: #0000ff;">this</span> Viewer viewer)<br /> {<br /> <span style="color: #0000ff;">foreach</span> (<span style="color: #0000ff;">var</span> control in viewer.Controls)<br /> <span style="color: #0000ff;">if</span> (control <span style="color: #0000ff;">is</span> ToolStrip)<br /> <span style="color: #0000ff;">return</span> (control <span style="color: #0000ff;">as</span> ToolStrip);<br /> <span style="color: #0000ff;">return null</span>;<br /> }<br />}<br /></div><br /><font style="font-family:Tahoma;font-size:10pt">Now we can access to viewer's toolbar using the code like:</font><br /><div style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;><br /><span style="color: #0000ff;">var</span> viewer = <span style="color: #0000ff;">new</span> DataDynamics.ActiveReports.Viewer.Viewer();<br />ToolStrip viewerToolStrip = viewer.CreateToolStrip();<br /></div><br /><font style="font-family:Tahoma;font-size:10pt">Let's see how we can implement several customization scenarios using this "secret" feature.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Scenario #1 - Composing the complex viewer toolbar</b></font><br /><font style="font-family:Tahoma;font-size:10pt">The following code builds the top panel of the <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.toolstripcontainer.aspx">tool strip container</a> by putting File Menu and Viewer Toolbar together:</font><br /><div style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;><br /><span style="color: #0000ff;">var</span> viewer = <span style="color: #0000ff;">new</span> DataDynamics.ActiveReports.Viewer.Viewer();<br />ToolStrip viewerToolStrip = viewer.CreateToolStrip();<br /><span style="color: #0000ff;">var</span> ms = <span style="color: #0000ff;">new</span> MenuStrip {Dock = DockStyle.Top};<br /><span style="color: #0000ff;">var</span> fileMenu = <span style="color: #0000ff;">new</span> ToolStripMenuItem(<span style="color: #006080;">"File"</span>);<br /><span style="color: #0000ff;">var</span> fileOpenMenu = <span style="color: #0000ff;">new</span> ToolStripMenuItem(<span style="color: #006080;">"Open"</span>, <span style="color: #0000ff;">null</span>, <span style="color: #0000ff;">delegate</span>{/*opening RDF file happens here*/});<br /><span style="color: #0000ff;">var</span> fileExitMenu = <span style="color: #0000ff;">new</span> ToolStripMenuItem(<span style="color: #006080;">"Exit"</span>, <span style="color: #0000ff;">null</span>, <span style="color: #0000ff;">delegate</span> {Application.Exit(); });<br />fileMenu.DropDownItems.Add(fileOpenMenu);<br />fileMenu.DropDownItems.Add(fileExitMenu);<br />ms.MdiWindowListItem = fileMenu;<br />ms.Items.Add(fileMenu);<br />toolStripContainer1.TopToolStripPanel.Join(ms,1);<br />toolStripContainer1.TopToolStripPanel.Join(viewerToolStrip, 2);<br /></div><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Scenario #2 - Customizing the native toolbar items</b></font><br /><font style="font-family:Tahoma;font-size:10pt">The following code removes the text from Print, Backward and Forward buttons and also removes Annotations button from the viewer toolbar:</font><br /><div style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;><br /><span style="color: #0000ff;">var</span> viewer = <span style="color: #0000ff;">new</span> DataDynamics.ActiveReports.Viewer.Viewer();<br />ToolStrip viewerToolStrip = viewer.CreateToolStrip();<br />viewerToolStrip.Items[2].Text = viewerToolStrip.Items[20].Text = viewerToolStrip.Items[21].Text = <span style="color: #0000ff;">string</span>.Empty;<br />viewerToolStrip.Items.RemoveAt(23);<br /></div><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Advanced scenario.</b></font><br /><font style="font-family:Tahoma;font-size:10pt">In the last code sample I used the magic numbers 2,20,21 and 23 to access to the toolbar items. How do I know those magic numbers? I got them by running the simple code which goes through the toolbar items and outputs the index, text and type of each item. Here is the resulting list:<br /><br />0 Table Of Contents:System.Windows.Forms.ToolStripButton<br />1 :System.Windows.Forms.ToolStripSeparator<br />2 &Print...:System.Windows.Forms.ToolStripButton<br />3 :System.Windows.Forms.ToolStripSeparator<br />4 Copy:System.Windows.Forms.ToolStripButton<br />5 :System.Windows.Forms.ToolStripSeparator<br />6 &Find:System.Windows.Forms.ToolStripButton<br />7 :System.Windows.Forms.ToolStripSeparator<br />8 Single Page View:System.Windows.Forms.ToolStripButton<br />9 Multiple Page View:#is.#5ml<br />10 Continuous Scroll:System.Windows.Forms.ToolStripButton<br />11 :System.Windows.Forms.ToolStripSeparator<br />12 Zoom Out:System.Windows.Forms.ToolStripButton<br />13 Zoom In:System.Windows.Forms.ToolStripButton<br />14 100 %:System.Windows.Forms.ToolStripComboBox<br />15 :System.Windows.Forms.ToolStripSeparator<br />16 Previous Page:System.Windows.Forms.ToolStripButton<br />17 Next Page:System.Windows.Forms.ToolStripButton<br />18 1/1:#is.#rs+#U.#ss<br />19 :System.Windows.Forms.ToolStripSeparator<br />20 &Backward:System.Windows.Forms.ToolStripButton<br />21 &Forward:System.Windows.Forms.ToolStripButton<br />22 :System.Windows.Forms.ToolStripSeparator<br />23 Annotations:System.Windows.Forms.ToolStripDropDownButton<br /><br />As you can see most of the toolbar items are buttons and separators. There are two mysterious items though in the list. Item 9 is one which allows to set the mode of multi-page view in the viewer. I will not focus on this element for now.<br />Item 18 is the text box which shows the current page number and the page total of the report which is shown by viewer. Access to the properties and events of that text box is <a href="http://www.datadynamics.com/forums/116229/ShowPost.aspx">sometimes needed</a>. As you can see this toolbar item is the instance of some internal class of Viewer assembly. We can't access to the properties and events of that internal class, but we can try cast it to ToolStripTextBox:<br /></font><br /><div style="font-size: small;color: black;font-family: Consolas, "Courier New", Courier, Monospace;background-color: #ffffff;><br /><span style="color: #0000ff;">var</span> viewer = <span style="color: #0000ff;">new</span> DataDynamics.ActiveReports.Viewer.Viewer();<br />ToolStrip viewerToolStrip = viewer.CreateToolStrip();<br /><span style="color: #0000ff;">var</span> pagesEditor = viewerToolStrip.Items[18] <span style="color: #0000ff;">as</span> ToolStripTextBox;<br /> pagesEditor.TextChanged += <span style="color: #0000ff;">delegate</span> { Debug.WriteLine(<span style="color: #006080;">"The current page was changed"</span>); };<br /></div><br /><font style="font-family:Tahoma;font-size:10pt">..and that works.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Disclaimer</b></font><br /><font style="font-family:Tahoma;font-size:10pt">The features which are described in this article are not officially supported. They are not tested and documented. They can change in further versions. Use them at your own risk.</font>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com2tag:blogger.com,1999:blog-5306024932265403945.post-7795431581851751842010-01-16T12:48:00.003+06:002010-01-16T13:29:12.720+06:00Return to the blog<font style="font-family:Tahoma;font-size:10pt">It's almost one year since from I made the last post in this blog. A lot of dramatic - good and terrible - events happened with me in 2009. I quit smoking, it was unexpectedly easy to do. Now I think that I was a complete idiot when was smoking twenty cigarettes per day. I almost quit drinking. Last two events where I drank the alcohol were the NY celebration and my mother birthday. My wedding plans were broken and me and my girlfriend stopped our relationships. I moved to the new apartments. My cat moved to my sister's house. I visited <a href="http://picasaweb.google.com/S.Abakumoff/Bulgaria2009#">Bulgaria</a> during my vacation. It's weird country! I started visiting gym twice per week. I lost about 5 kilograms of weight.<br />The worst thing that might happen did not happen - our company still alive and kicking! We saved our work. We are going to work on the new generation of the best reporting tool ever.<br />Anyway, all that stuff in the past. I hope that 2010 will be better than 2009. One of the things I plan is returning to the blog. I am getting a lot of ideas about which I would like to blog. I plan to shed the light to some aspects of <a href="http://www.datadynamics.com/Products/ActiveReports/Overview.aspx">ActiveReports 6</a> and <a href="http://www.datadynamics.com/Products/DDRPT/Overview.aspx">Data Dynamics Reports</a> internals. I got a lot of experience with <a href="http://www.asp.net/mvc/">ASP.NET MVC</a> and have several topics to blog about. Finally I faced several questionable OOP decisions about which I want to blog as well. <br /></font>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com0tag:blogger.com,1999:blog-5306024932265403945.post-50467953765518591782010-01-16T12:43:00.002+06:002010-01-16T12:47:59.053+06:00C# dynamic types and the design patterns.<font style="font-family:Tahoma;font-size:12pt;color:RED"><b>NOTES</b></font><br /><font style="font-family:Tahoma;font-size:10pt">This post is resurrected. I accidentally deleted this earlier.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Preface</b></font><br /><font style="font-family:Tahoma;font-size:10pt">The question that gives me no rest lately is how I can use <a href="http://icodethereforeiam.blogspot.com/2009/01/c-40-first-look-at-dynamicity.html">C# 4.0 dynamic features</a> in the real-world .NET applications. For a long time I had no ideas except of using dynamic objects in LINQ queries. It is briefly discussed in the comments to <a href="http://icodethereforeiam.blogspot.com/2009/01/c-40-first-look-at-dynamicity.html">C# 4.0 - the first look at the DYNAMICITY</a> post. But today I know another answer and it seems to be breathtaking. The answer is we don't need to use the <a href="http://en.wikipedia.org/wiki/Design_pattern_(computer_science)">OOP design patterns</a> if we have the support of the "Dynamicity Forces".</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Design patterns</b></font><br /><font style="font-family:Tahoma;font-size:10pt"><a href="http://en.wikipedia.org/wiki/Design_pattern_(computer_science)">Design patterns</a> are part of the fundamental of Object Oriented Programming. Tremendous amount of resources have appeared on design patterns after the book <a href="http://en.wikipedia.org/wiki/Design_Patterns">Design Patterns: Elements of Reusable Object-Oriented Software</a> was published in 1994. Each person involved in OOP programming was learning the design patterns. I used to use the design patterns in my every-day-work. Design patterns typically show relationships and interactions between classes or objects, without specifying the final application classes or objects that are involved. Technically that means that the type of the object which is passed to be handled by the application <span style="font-style:italic;">isn't known at compile time</span>. Design patterns use the objects inheritance, composition, etc. to effectively solve the problem then the final object type isn't known at compile time. But wait...now we have the C# dynamic types which is intended to be used when the type of an object isn't known at compile time! Yes, I assert that any well-known design pattern can be avoided by using the dynamic types. Let me show the example.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Bridge design pattern(classic approach).</b></font><br /><font style="font-family:Tahoma;font-size:10pt"><a href="http://en.wikipedia.org/wiki/Bridge_pattern">Bridge design pattern</a> is very powerful and applies to many situations. Its purpose - "decouple an abstraction from its implementation so that the two can vary independently" - is not possible to understand without the real-world example. The classic example is shown below. I copied the code from the <a href="http://en.wikipedia.org/wiki/Bridge_pattern">wikipedia article</a> and updated it a bit(C# 3.0 is used). <p style="background:lightgray">internal interface IDrawingAPI<br />{<br /> void DrawCircle(double x, double y, double radius);<br /> void DrawLine(double x1, double y1, double x2, double y2);<br />}<br /><br />internal class DrawingAPI1 : IDrawingAPI<br />{<br /> public void DrawCircle(double x, double y, double radius)<br /> {<br /> Console.WriteLine("API1.circle at {0}:{1} radius {2}", x, y, radius);<br /> }<br /> public void DrawLine(double x1, double y1, double x2, double y2)<br /> {<br /> Console.WriteLine("API1.line from {0},{1} to {2},{3}", x1, y1, x2, y2);<br /> }<br />}<br /><br />internal class DrawingAPI2 : IDrawingAPI<br />{<br /> public void DrawCircle(double x, double y, double radius)<br /> {<br /> Console.WriteLine("API2.circle at {0}:{1} radius {2}", x, y, radius);<br /> }<br /> public void DrawLine(double x1, double y1, double x2, double y2)<br /> {<br /> Console.WriteLine("API2.line from {0},{1} to {2},{3}", x1, y1, x2, y2);<br /> }<br />}<br /><br />internal interface IShape<br />{<br /> void Draw();<br />}<br /><br />internal sealed class LineShape : IShape<br />{<br /> public double X1 { get; set; }<br /> public double X2 { get; set; }<br /> public double Y1 { get; set; }<br /> public double Y2 { get; set; }<br /> public IDrawingAPI DrawingAPI { get; set; }<br /> public void Draw()<br /> {<br /> DrawingAPI.DrawLine(X1, Y1, X2, Y2);<br /> }<br />}<br /><br />internal class CircleShape : IShape<br />{<br /> public IDrawingAPI DrawingAPI{ get; set;}<br /> public double X{ get; set;}<br /> public double Y{ get; set;}<br /> public double Radius{ get; set;}<br /> public void Draw()<br /> {<br /> DrawingAPI.DrawCircle(X, Y, Radius);<br /> }<br />}<br /><br />internal class BridgePatternClient<br />{<br /> public static void Main(string[] args)<br /> {<br /> var shapes = new IShape[2];<br /> shapes[0] = new CircleShape {X = 1, Y = 2, Radius = 3, DrawingAPI = new DrawingAPI1()};<br /> shapes[1] = new LineShape {X1 = 1, Y1 = 2, X2 = 3, Y2 = 4, DrawingAPI = new DrawingAPI2()};<br /> foreach (IShape shape in shapes)<br /> {<br /> shape.Draw();<br /> }<br /> }<br />}</p> In this example bridge design pattern is used to decouple the shape abstraction from the drawing implementation. Indeed there are alternate ways to design such a system, but these ways have the important design flaws. This is greatly described in <a href="http://www.amazon.com/Design-Patterns-Explained-Perspective-Object-Oriented/dp/0201715945">Design Patterns Explained: A New Perspective on Object-Oriented Design </a> book(must read!). Now let me show how I can accomplish the same task as shown above by using dynamic types.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Dynamicity in action.</b></font><br /><font style="font-family:Tahoma;font-size:10pt">The code that shown below is written in Visual Studio 2010 and it works fine. It's so simple that doesn't need to be explained. Just look at this.<p style="background:lightgray">internal sealed class DrawingAPI1<br />{<br /> public void DrawCircle(double x, double y, double radius)<br /> {<br /> Console.WriteLine("API1.circle at {0}:{1} radius {2}", x, y, radius);<br /> }<br /> public void DrawLine(double x1, double y1, double x2, double y2 )<br /> {<br /> Console.WriteLine("API1.line from {0},{1} to {2},{3}", x1, y1, x2, y2);<br /> }<br />}<br /><br />internal sealed class DrawingAPI2<br />{<br /> public void DrawCircle(double x, double y, double radius)<br /> {<br /> Console.WriteLine("API2.circle at {0}:{1} radius {2}", x, y, radius);<br /> }<br /> public void DrawLine(double x1, double y1, double x2, double y2)<br /> {<br /> Console.WriteLine("API2.line from {0},{1} to {2},{3}", x1, y1, x2, y2);<br /> }<br />}<br /><br />internal sealed class Line<br />{<br /> public double X1 { get; set; }<br /> public double X2 { get; set; }<br /> public double Y1 { get; set; }<br /> public double Y2 { get; set; }<br /> public <span style="font-weight:bold;">dynamic</span> DrawingAPI { get; set; }<br /> public void Draw()<br /> {<br /> DrawingAPI.DrawLine(X1, Y1, X2, Y2);<br /> }<br /> }<br /><br />internal sealed class Circle<br />{<br /> public double X { get; set; }<br /> public double Y { get; set; }<br /> public double Radius { get; set; }<br /> public <span style="font-weight:bold;">dynamic</span> DrawingAPI { get; set; }<br /> public void Draw()<br /> {<br /> DrawingAPI.DrawCircle(X, Y, Radius);<br /> }<br />}<br /> <br />public class Program<br />{<br /> [STAThread]<br /> static void Main()<br /> {<br /> DrawingAPI1 api1 = new DrawingAPI1();<br /> DrawingAPI2 api2 = new DrawingAPI2();<br /> <span style="font-weight:bold;">dynamic</span>[] shapes = { new Line { X1 = 1, Y1 = 1, X2 = 2, Y2 = 3, DrawingAPI = api1 },<br /> new Circle { X = 10, Y = 20, Radius = 40.4f, DrawingAPI = api2 }<br /> };<br /> foreach (<span style="font-weight:bold;">dynamic</span> shape in shapes)<br /> {<br /> shape.Draw();<br /> }<br /> }<br />}<br /></p>So, when we don't know the final type of the Shape and Drawing API we use dynamic type. Do you like it?</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>In conclusion.</b></font><br /><font style="font-family:Tahoma;font-size:10pt">This post is about dynamic features of C# of course. But it brings up more general question. In our days the programming technologies changes are incredible. It's good practice to keep up with Changes. But sometimes the changes can make us forgetting the good, old-fashioned technologies. I think that we should be careful with this effect. The new technologies can be awesome, greatly suitable for my needs. The old technologies can also be suitable for the problems I solve. A good problem-solver tries several possible solutions and selects the best one. A good problem-solver doesn't use the technology just because it is cutting-edge.</font>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com0tag:blogger.com,1999:blog-5306024932265403945.post-13513084126305331232009-02-15T19:42:00.005+06:002009-02-15T19:59:33.866+06:00Fun with error messages<font style="font-family:Tahoma;font-size:10pt">Recently I posted some thoughts about <a href="http://icodethereforeiam.blogspot.com/2009/01/error-message-fresh-glance.html">error messages construction</a>. Today I found the nice example which shows how the error message should <span style="font-style:italic;">not</span> be constructed. This year we started to use <a href="http://www.seapine.com/surroundscm.html">Surround SCM</a> for the source code of our products. Today I get the following error when tried to check the sources out:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiM6IWtxKYgm_gdnbqfT4tCCxuuVsT0Z6RUOVoYUQbYBAZzC2aZhUTh7WMza4Sq_ShhfgbwbhYHDTuk-XaGa_g_ySasQ6z6CnnoniEQ4bFg8ftIbDziaGtJ1DL1chcX0N3TUEaynB4jHd_Z/s1600-h/error.PNG"><img style="cursor:pointer; cursor:hand;width: 400px; height: 271px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiM6IWtxKYgm_gdnbqfT4tCCxuuVsT0Z6RUOVoYUQbYBAZzC2aZhUTh7WMza4Sq_ShhfgbwbhYHDTuk-XaGa_g_ySasQ6z6CnnoniEQ4bFg8ftIbDziaGtJ1DL1chcX0N3TUEaynB4jHd_Z/s400/error.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5303021721578168770" /></a><br />"Surround SCM encountered an error. Communication error." The phrase seems very familiar to me..Yeah! "My Name is Bond - James Bond". There is no any other sense with such an error message except of it looks very funny. When you report about the error, don't make people laugh, tell them as much helpful information as possible.</font>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com0tag:blogger.com,1999:blog-5306024932265403945.post-86824593314691247182009-02-06T21:29:00.004+06:002009-02-08T23:11:40.342+06:00MEF – The new extensibility standard<font style="font-size: 12pt; color: #4f81bd; font-family: tahoma"><b>Preface</b></font><br /><font style="font-size: 10pt; font-family: tahoma">One of the most impressive technologies knocked out by Microsoft was <a href="http://en.wikipedia.org/wiki/Windows_Communication_Foundation">Windows Communication Foundation</a>. WCF unified various communication capabilities that exists in .NET 2.0 into a single, common, general framework. I think that it is the great achievement!<br />Recently I found <a href="http://www.microsoft.com/downloads/details.aspx?familyid=752cb725-969b-4732-a383-ed5740f02e93&displaylang=en">Visual Studio 2010 training kit</a> which includes the set of the hand-on-labs. One of the labs is called "Introduction To Managed Extensibility Framework". I read the instructions and it made me excited. <a href="http://www.codeplex.com/MEF">Managed Extensibility Framework</a> unifies the application extensibility capabilities! Actually .NET doesn't provide any "standard" API's for the applications extensibility. There is the <a href="http://en.wikipedia.org/wiki/Plugin">plug-in model</a> which should be implemented from scratch by every application that wants to support it. <a href="http://en.wikipedia.org/wiki/Windows_Presentation_Foundation">WPF</a> provides the ways for look-and-feel extensibility by using styles, templates, skins and themes. But until now there was no the technology that unifies the extensibility like WCF unifies the communication. Managed Extensibility Framework is unifier guy for the extensibility. In this post I will try to describe my experience with MEF and provide the real-world code sample.<br /></font><br /><font style="font-size: 12pt; color: #4f81bd; font-family: tahoma"><b>MEF architecture</b></font><br /><font style="font-size: 10pt; font-family: tahoma">The MEF architecture is shown <a href="http://www.codeplex.com/MEF/Wiki/View.aspx?title=Architecture">here</a>. It is very simple and the extensibility implementation can be described in the following steps:<br /><ul><li>The application provides the set of extensibility points using MEF API.</li><li>The application hosts the extensibility parts container using MEF API.</li><li>The plug-in provides the set of extensibility parts using MEF API.</li><li>The application imports the extensibility parts using MEF API.</li></ul> The API is pretty straightforward and it's very easy to implement the extensibility support in your application using MEF.<br /></font><br /><font style="font-size: 12pt; color: #4f81bd; font-family: tahoma"><b>The real-world sample.</b></font><br /><font style="font-size: 10pt; font-family: tahoma">Recently I was thinking about providing one more extensibility facilities for <a href="http://www.datadynamics.com/Products/DDRPT/default.aspx">Data Dynamics Reports</a>. Briefly - it should provide the capability to use the custom UI editors of some entities. For the real-world sample I selected the similar task:<br /><i>WPF application provides the editor of the color of something. For example the application for <a href="http://en.wikipedia.org/wiki/Facial_composite">facial composite</a> construction uses the editor for eyes color. The application should provide the built-in color editor and end-user should be able to specify the custom color editor.</i><br />For example : the application provides built-in color editor that allows editing of the Red, Green and Blue color components. End-user can select the custom color editor that allows editing the Hue, Saturation and Brightness color components. The application should provide the visual feedback whenever the selected color is changed.</font><br /><br /><font style="font-size: 12pt; color: #4f81bd; font-family: tahoma"><b>Implementation of the built-in color editor.</b></font><br /><font style="font-size: 10pt; font-family: tahoma">So, the built-in color editor allows editing of the Red, Green and Blue color components. WPF doesn't provide the standard color editor and we need to implement it. The implementation of the RGB color editor is straightforward task. We should:<ul type="disc"><li>Define the <a href="http://msdn.microsoft.com/en-us/library/ms752914.aspx">dependency properties</a> for the Red, Green and Blue components.</li><li>Define the dependency property for the currently selected color.</li><li>Provide the way which can be used by the hosting application to intercept the event when the selected color is changed.</li></ul>The last thingie is a bit of pain. There is the <a href="http://msdn.microsoft.com/en-us/magazine/cc794276.aspx">beautiful article</a> that describes this pain and offers the various solutions for intercepting the event of changing the dependency property value. I will use the simple event(i.e. not <a href="http://msdn.microsoft.com/en-us/library/ms742806.aspx">routed event</a>) to allow intercepting the selected color changing. Since all that application should know about the color editor is how to intercept the color changing event, I will define the new interface that provides this event and implement this interface in the built-in color editor. There are several alternate ways to design this system, but for it doesn't matter for the topic I discuss. The basic code that defines the color editor control, the dependency property for Red component, the dependency property for the currently selected color and another needed stuff is shown below.<p style="background:lightgray"> interface IColorChanged<br /> {<br /> event ColorChangedEventHandler ColorChanged;<br /> }<br /> <br /> delegate void ColorChangedEventHandler(object sender, ColorChangedEventArgs args);<br /> <br /> class ColorChangedEventArgs : EventArgs<br /> {<br /> public Color OldValue{ get; set;}<br /> public Color NewValue{ get; set;}<br /> } <br /> <br />class RGBColorEditor : Control, IColorChanged<br />{<br /> private Color _color = Colors.Black;<br /> public event ColorChangedEventHandler ColorChanged;<br /><br /> public ColorEditor()<br /> {<br /> SetValue(RProperty, _color.R);<br /> SetValue(SelectedColorProperty, _color);<br /> }<br /><br /> public static readonly DependencyProperty RProperty = <br /> DependencyProperty.Register("R", typeof (byte), typeof (RGBColorEditor),<br /> new PropertyMetadata((byte)255, OnRChanged));<br /><br /> public static readonly DependencyProperty SelectedColorProperty =<br /> DependencyProperty.Register("SelectedColor", typeof(Color), typeof(RGBColorEditor), new PropertyMetadata(Colors.Black, OnSelectedColorChanged));<br /> <br /> public byte R<br /> {<br /> set { SetValue(RProperty, value); }<br /> get { return (byte)GetValue(RProperty); }<br /> }<br /> <br /> private void OnRChanged(byte newValue)<br /> {<br /> _color.R = newValue;<br /> SetValue(SelectedColorProperty, _color);<br /> }<br /> <br /> private static void OnRChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)<br /> {<br /> (d as ColorEditor).OnRChanged((byte)e.NewValue);<br /> }<br /><br /> private void OnSelectedColorChanged(DependencyPropertyChangedEventArgs e)<br /> {<br /> if (ColorChanged != null)<br /> ColorChanged(this, new ColorChangedEventArgs { NewValue = (Color)e.NewValue, OldValue = (Color)e.OldValue });<br /> }<br /> <br /> private static void OnSelectedColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)<br /> {<br /> (d as ColorEditor).OnSelectedColorChanged(e);<br /> }<br />}<br /></p>The rest of the code defines the dependency properties for the green and blue components of the color and also provides the default control template. RGBColorEditor is contained in the main application assembly.</font><br /><br /><font style="font-size: 12pt; color: #4f81bd; font-family: tahoma"><b>Custom color editor sample.</b></font><br /><font style="font-size: 10pt; font-family: tahoma">So, our custom editor control will allow editing of the Hue, Saturation and Brightness color components. The implementation would be very similar to RGBColorEditor. We implement IColorChanged interface, define the dependency properties for Hue, Saturation, Brightness and SelectedColor properties. Here is the snippet of the code:<p style="background:lightgray"> class HSBColorEditor : Control, IColorChanged<br /> {<br /> private static Color ConvertHsbToRgb(double h, double s, double b)<br /> {<br /> //return new color created from h,s,b values;<br /> }<br /> public static readonly DependencyProperty RProperty =<br /> DependencyProperty.Register("H", typeof(double), typeof(HSBColorEditor),<br /> new PropertyMetadata(0, OnHChanged));<br /> <br /> void OnHChanged(double newValue)<br /> {<br /> Color newColor = ConvertHsbToRgb(newValue, S, B);<br /> SetValue(SelectedColorProperty, newColor);<br /> }<br /> <br /> private static void OnHChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)<br /> {<br /> (d as HSBColorEditor).OnHChanged((double)e.NewValue);<br /> }<br />}</p>HSBColorEditor class is contained in the separate assembly. Let's say its name is FacialCompositeCustomControls.</font><br /><br /><font style="font-size: 12pt; color: #4f81bd; font-family: tahoma"><b>Extensibility without MEF.</b></font><br /><font style="font-size: 10pt; font-family: tahoma">I think that the most suitable way to provide the extensibility facility without MEF is using <a href="http://msdn.microsoft.com/en-us/library/ms972319.aspx">Provider Model Design Pattern</a>. The application configuration file would have the list of the available color editors, the application would provide end-user with UI that shows this list and allows selecting the appropriate editor. Then the application would create the selected control instance and add it to the corresponding place.</font><br /><br /><font style="font-size: 12pt; color: #4f81bd; font-family: tahoma"><b>MEF world.</b></font><br /><font style="font-size: 10pt; font-family: tahoma">For our application purpose we will use the color editor selector dialog which is responsible for collecting the custom color editor implementations and allowing end-user to select the appropriate editor. The color editor selector will try collecting the color editors from the assemblies located in the Plugin folder of the the directory of the executing application. Also, the built-in color editor should be added in the collection. So, the first thing that we should do if defining the extensibility points in the color editor selector. MEF allows to do that by using different ways, but the key is System.ComponentModel.Composition.ImportAttribute. Look at the code:<p style="background:lightgray">class ColorEditorSelector : Window<br /> {<br /> [Import(typeof(IColorChanged))]<br /> private ExportCollection<Control> EditorCollection { get; set; }<br /> public Control SelectedEditor { get; set; }<br />}</p>We defined the extensibility point using ImportAttribute and set the contract for the plug-in - it should implement IColorChanged interface. The color editor collection will be stored in the property of type System.ComponentModel.Composition.ExportCollection<Control>. SelectedEditor property is used by the application to get the color editor selected by user. Then we need to add the code which looks for the available color editors in the executing assembly and Plugin folder. The code is shown below. In the MEF terms we will add the composition container which loads the compositions parts from the executing assembly and from Plugins folder. <p style="background:lightgray">private void Compose()<br />{<br /> var catalog = new AggregateCatalog();<br /> var catalog1 = new AssemblyCatalog(typeof(ColorEditorSelector).Assembly);<br /> catalog.Catalogs.Add(catalog1);<br /> var catalog2 = new DirectoryCatalog("Plugins", true);<br /> catalog.Catalogs.Add(catalog2);<br /> var container = new CompositionContainer(catalog);<br /> var batch = new CompositionBatch();<br /> batch.AddPart(this);<br /> container.Compose(batch);<br />}</p>This code is like design pattern for the composition. It defines several places from which the extensible parts can be loaded, adds them to the container and performs the composition. The composition batch is used for the dynamic re-composition. I.e. if one copies the new assembly contains the custom color editor in Plugins folder, then it is handled dynamically without re-run the application. Compose method is called from ColorEditorSelector constructor. Here is the code that runs the composition and fills the listbox by the type names of the available color editors:<p style="background:lightgray">public ColorEditorSelector()<br />{<br /> Compose();<br /> var list = new ListBox();<br /> foreach(var colorEditor in EditorCollection)<br /> {<br /> var control = colorEditor.GetExportedObject();<br /> list.Items.Add(control.GetType().Name);<br /> }<br />}<br /></p>The last thing that we should do is add the extensibility points definition in the color editor implementations. It is done by using System.ComponentModel.Composition.ExportAttribute:<p style="background:lightgray">[Export(typeof(IColorChanged))]<br />internal sealed class RGBColorEditor : Control, IColorChanged<br /><br />[Export(typeof(IColorChanged))]<br />internal sealed class HSBColorEditor : Control, IColorChanged</p>And that's all about the extensibility. The rest of ColorEditorSelector dialog composes the UI which allows to select the appropriate color editor and sets SelectedEditor accordingly. The application uses the SelectedEditor to add it to UI. Looks very straightforward and great, isn't it?</font><br /><br /><font style="font-size: 12pt; color: #4f81bd; font-family: tahoma"><b>In conclusion.</b></font><br /><font style="font-size: 10pt; font-family: tahoma">MEF is included in .NET Framework 4.0 CTP and I think it is really new standard for the application extensibility. Microsoft did the great job in design and implementation of MEF library and I will definitely will use it!</font>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com1tag:blogger.com,1999:blog-5306024932265403945.post-28904569021858739582009-01-30T22:21:00.002+06:002009-01-31T00:42:17.756+06:00Conceptual blocks and programming tasks. Part II.<font style="font-family:Tahoma;font-size:12pt;color:#4F81BD;"><b>Preface</b></font><br /><font style="font-family:Tahoma;font-size:10pt">In the <a href="http://icodethereforeiam.blogspot.com/2009/01/preface-one-of-my-favorite-nonfictional.html">previous post</a> I offered the following problem to solve:<br /><i>The input data is the <a href="http://en.wikipedia.org/wiki/Graph_(mathematics)">graph</a> representation, for example the instance of <a href="http://msdn.microsoft.com/en-us/library/he2s3bh7(VS.80).aspx?ppud=4">LinkedList</a> class. The output is Boolean value which is true if the graph has the cycle and false otherwise. The constraints are no additional memory should be used.</i><br />Let me publish the solution and the comments.<br /> </font><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD;"><b>The solution.</b></font><br /><font style="font-family:Tahoma;font-size:10pt">To show the solution, I would like to use C# language. I realized that <a href="http://msdn.microsoft.com/en-us/library/he2s3bh7(VS.80).aspx?ppud=4">LinkedList<T></a> class which I referred in the puzzle definition can't represent the graph that has cycles because the methods of this class don't allow to set the next and previous node to the node which already belongs the list. So, the following class is used to show the solution.<br /><p style="background:lightgray">internal class GraphNode<T><br />{<br /> private T _value;<br /> private GraphNode<T> _next;<br /> public GraphNode(T value)<br /> {<br /> _value = value;<br /> }<br /> public GraphNode<T> Next<br /> {<br /> get{ return _next;}<br /> set{ _next = value;}<br /> }<br /> public override string ToString()<br /> {<br /> return _value.ToString();<br /> }<br />}</p>And here is the solution:<br /><p style="background:lightgray">static bool HasCycle<T>(List<GraphNode<T>> list)<br />{<br /> if (list == null)<br /> throw new ArgumentNullException("list");<br /> if (list.Count == 0)<br /> throw new ArgumentException("empty list", "list");<br /> GraphNode<T> current1 = list[0];<br /> GraphNode<T> current2 = list[0];<br /> do<br /> {<br /> if (current1.Next == null || current2.Next == null || current2.Next.Next == null)<br /> {<br /> return false;<br /> }<br /> current1 = current1.Next;<br /> current2 = current2.Next.Next;<br /> if (ReferenceEquals(current1, current2))<br /> {<br /> return true;<br /> }<br /> } while (current1 != null && current2 != null);<br /> return false;<br />}<br /></p></font><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD;"><b>The Analysis.</b></font><br /><font style="font-family:Tahoma;font-size:10pt">The idea behind the scene is very simple. The solution is using two pointers to the graph nodes, the first pointer goes through the graph with step 1(current1=current.Next) and the second pointer goes through the graph with step 2(current2=current.Next.Next). If the graph has the cycle, these two pointers will refer to the same node at some point which is obvious.However, I seen a lot of situations when people were not able to solve this puzzle quickly or didn't solve it at all.When I was asked to solve this puzzle several years ago I didn't solve it as well. And the reason of that is the conceptual blocks.<br />When I studied at the university, we learned the common algorithms and implemented them quite intensively. A lot of the algorithms dealt with the graphs - visiting the graph nodes, finding the shortest way between two graph nodes, etc. I used to use single pointer to the graph nodes for these algorithms. After more than 5 years this habit still persisted. This is some sort of the stereotype which is definitely the conceptual block. The second block is the same as I shown in the <a href="http://icodethereforeiam.blogspot.com/2009/01/preface-one-of-my-favorite-nonfictional.html">previous post</a> - the tendency to delimit the problem area poorly. Sometimes people restrict themselves to using the single pointer. If one would know about the conceptual blocks and control the process of the problem solving, the "finding the cycle in the graph" become the pretty trivial task.</font>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com0tag:blogger.com,1999:blog-5306024932265403945.post-41811629754845151452009-01-26T22:25:00.006+06:002009-01-26T23:12:34.957+06:00Conceptual blocks and programming tasks.<font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Preface</b></font><br /><font style="font-family:Tahoma;font-size:10pt">One of my favorite nonfictional books is <a href="http://www.amazon.com/Conceptual-Blockbusting-Guide-Better-Ideas/dp/0201550865">“Conceptual Blockbusting” by James L. Adams</a>. The book describes the conceptual blocks which are “mental walls that blocks the problem solver from correctly perceiving a problem or conceiving its solution”. There is the set of puzzles that intended to understand how the conceptual blocks can hamper the problem solving. I believe that reading this book can really help you to become a better thinker. Indeed it’s helpful if you aren’t a genius like Albert Einstein. Every time I read this book I try to figure out how the conceptual blocks can hamper the solving of the problems that I face doing my job every day. And recently I found the interesting issue…</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Delimiting the problem area poorly.</b></font><br /><font style="font-family:Tahoma;font-size:10pt">One of the perceiving conceptual blocks is tendency to delimit the problem too closely. It is demonstrated using the following puzzle: <br /><i>Draw no more than four straight lines without lifting the pencil from the paper which will cross through all nine dots:</i><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHzRWrAE63N2QNl_tptIAk31O2TJUBbm6_m2i_l3IBY3CghXALa60D0vm63_4c5CmupwDYwj0qT_s1c9On6bs-MStwiDrmrkEAO9s_GR3IR6kwa-JnIWABq7EXbCf7xRc6lZP-JgYxuF7B/s1600-h/Puzzle5.png"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 137px; height: 136px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHzRWrAE63N2QNl_tptIAk31O2TJUBbm6_m2i_l3IBY3CghXALa60D0vm63_4c5CmupwDYwj0qT_s1c9On6bs-MStwiDrmrkEAO9s_GR3IR6kwa-JnIWABq7EXbCf7xRc6lZP-JgYxuF7B/s200/Puzzle5.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5295648975668916754" /></a><br />Work on it a while. One possible solution is shown <a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhO0TSsN1yE3sKCPKpxs8HXLUYPzSyUo2fPg8Ia8SXfWZE19oi67aqNfOy9UYq_sfA92aLIeCz3oZxoxO_IkRR57o21hJbUhNh3gi-xYYl8IQwe_e4MrPtQx-Rh8eK0bNWz1hNE5GPK08Hr/s1600-h/Puzzle4.png">here</a><br />A lot of people don’t exceed the imaginary boundary even though it is not in the definition of the problem at all. The overly strict limits are a block in the mind of the solver.<br /></font><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Find cycle in the graph puzzle</b></font><br /><font style="font-family:Tahoma;font-size:10pt">Consider the following puzzle.<br /><i>The input data is the <a href="http://en.wikipedia.org/wiki/Graph_(mathematics)">graph</a> representation, for example the instance of <a href="http://msdn.microsoft.com/en-us/library/he2s3bh7(VS.80).aspx?ppud=4">LinkedList</a> class. The output is Boolean value which is true if the graph has the cycle and false otherwise. The constraints are no additional memory should be used.</i><br />Try to solve this puzzle. In the next post I will explain the issues that hamper this puzzle solving and why they appear.</font>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com0tag:blogger.com,1999:blog-5306024932265403945.post-50929772241021354122009-01-24T21:30:00.002+06:002009-01-24T21:38:39.555+06:00C# 4.0 - the first look at the DYNAMICITY.<font style="font-family:Tahoma;font-size:10pt">This week I looked at C# dynamic features that were added in C# 4.0 CTP and Visual Studio 2010. Tremendous amount of resources have appeared on dynamic features of C# over the web. C# developers provided the description of dynamic features on their blogs, i.e. <a href="http://blogs.msdn.com/samng/default.aspx">Sam Ng’s blog</a> and <a href="http://blogs.msdn.com/cburrows/default.aspx">Chris Borrows’ blog</a> have the great posts about the topic. However, not all the dynamic features are available in C# 4.0 2008 CTP. I.e. a lot of samples listed in the mentioned blogs don’t event compile in the current VS.NET 2010 preview. So I didn’t dive in the specific language constructions and tricks. What makes me excited is step forward to “dynamicity” in .NET. I never worked with dynamic languages before but apparently it’s about time to learn more about the dynamic languages facilities. Well, I found <a href="http://msdn.microsoft.com/en-us/magazine/default.aspx">MSDN magazine</a> article called <a href="http://msdn.microsoft.com/en-us/magazine/cc300810.aspx">CLR Inside out: IronPython</a> and read the beautiful thing:<br /><br /><i>The most common question I hear about dynamic languages is "why should I use them?" Trying to show a longtime C++ or C# developer that a dynamic language is useful for problems outside the scripting domain is difficult. One concrete benefit of dynamic languages is that they facilitate an iterative development cycle. The interactive capabilities of dynamic languages make them a better match for this type of cycle than compiled languages. Developers can focus on exploring and prototyping functionality, refactoring if necessary, and then repeating with new functionality. This allows for a more exploratory process of development than the code/build/run/debug loop that most other languages constrain the programmer to.</i><br /><br />So, the dynamic language, well C# 4.0, will allow transition from code/build/run/debug loop to evaluation/print loop? Yes, in PDC 2008 <a href="http://channel9.msdn.com/pdc2008/TL16/">“Future of C#”</a> talk Anders Hejlsberg shows it in action and it looks amazing. The new language features like dynamic type, IDynamicLanguage interface, optional and named parameters also look very promising. Next week I will try to work with C# 4.0 as with dynamic language, I think the best way to do this is get some problem, solve it using C# 3.0(statically typed language), then solve it using C#4.0(dynamic language). I will write about any interesting stuff.</font>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com2tag:blogger.com,1999:blog-5306024932265403945.post-25204919849955468682009-01-13T22:20:00.005+06:002009-01-14T10:19:06.042+06:00The Error Message - the fresh glance.<font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Preface</b></font><br /><font style="font-family:Tahoma;font-size:10pt"><a href="http://msdn.microsoft.com/en-us/magazine/dd264793.aspx">December 2008 issue</a> of <a href="http://msdn.microsoft.com/en-us/magazine/default.aspx">MSDN magazine</a> introduces the new column called <a href="http://msdn.microsoft.com/en-us/magazine/dd263095.aspx">Usability in Practice</a>. <a href="http://msdn.microsoft.com/en-us/magazine/dd365186.aspx">January 2009 issue</a> includes the first Usability in Practice <a href="http://msdn.microsoft.com/en-us/magazine/2009.01.usabilityinpractice.aspx">article</a> from which I learned something new.<br />The article itself isn't very worth. Almost entire content of the article is brief description of <a href="http://msdn.microsoft.com/en-us/library/aa511267.aspx">Error Message guidelines</a> part of <a href="http://msdn.microsoft.com/en-us/library/aa511258.aspx">Windows Vista Users Experience Guidelines</a>. Error message guideline has the great, comprehensive and straightforward directions of how the application error messages should be constructed. Actually the guideline has two logical parts - what information should be presented by the error message and how the error message should look like. The first part is quite clear and just tells us which points and questions we should consider for good error messages constructing. The second part - how the error message dialog should look like - is the thing which this post about.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Task Dialog</b></font><br /><font style="font-family:Tahoma;font-size:10pt">Windows Vista introduces a new standard dialog box called <a href="http://msdn.microsoft.com/en-us/library/aa511299.aspx">task dialog</a>. According to the error messages guideline the task dialogs should be used to show the error message if the error can't be fixed immediately, if the error isn't contextual user input problem and if the error isn't delayed detected problem. I.e. <a href="http://msdn.microsoft.com/en-us/magazine/2009.01.usabilityinpractice.aspx">When Things Go Wrong</a> article demonstrates <a href="http://i.msdn.microsoft.com/dd347820.fig03_L(en-us).gif">how the simple error message can be presented by the task dialog</a>. Here is the table that shows the correspondence between the task dialog areas and the <i>simple</i> error message parts.<br /><table><tr><td><b>Task dialog area</b></td><td><b>Error message part</b></td></td></tr> <tr><td>Title bar</td><td>A problem. States that a problem occurred.</td></tr><tr><td>Main instruction</td><td>A cause. Explains why the problem occurred.</td></tr><tr><td>Content area</td><td>A solution. Provides a solution so that users can fix the problem.</td></tr><tr><td>Command area</td><td>Commit button(Close).</td></tr></table></font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Using task dialog in .NET application.</b></font><br /><font style="font-family:Tahoma;font-size:10pt">The managed code can create and show the task dialog using the corresponding <a href="http://msdn.microsoft.com/en-us/library/bb756938.aspx">API</a>. The example of wrapping task dialog API in the managed code can be found in <a href="http://www.codeproject.com/KB/vista/TaskDialogWinForms.aspx">CodeProject</a>.<br />But the task dialog API is supported only by Vista. What about earlier versions of Windows? Which dialog we should use for show the error message if the application is run in Windows XP? What about using <a href="msdn.microsoft.com/en-us/library/system.windows.forms.messagebox.aspx">MessageBox</a> class? Unfortunately, MessageBox dialog doesn't allow distinguish between the main instruction area and the content area which I referred above. However, I think we definitely should follow the error message guideline and at least simulate the task dialog for non-Vista(and non-Windows 7) OS. At least for the simple error message we should show the dialog which has the parts described above. Here is the very basic sample of error message dialog that can be used in Windows XP:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOW4YGWjFaheQxnCVDLdAf7KE2gPhKCezO67MFcLIXw9wg2_MXRvgtkbLc32ctGca2bSIogTp-3GXNC3NrEnL2Igg0ABoIc3GJ0E234Ws-G5UQZVUkco62s9tsiMCE_NB9MwilgcIZf4DH/s1600-h/TaskDialog.PNG"><img style="cursor:pointer; cursor:hand;width: 400px; height: 115px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOW4YGWjFaheQxnCVDLdAf7KE2gPhKCezO67MFcLIXw9wg2_MXRvgtkbLc32ctGca2bSIogTp-3GXNC3NrEnL2Igg0ABoIc3GJ0E234Ws-G5UQZVUkco62s9tsiMCE_NB9MwilgcIZf4DH/s400/TaskDialog.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5290841138493851602" /></a><br />The sample of task dialog emulator can be found in <a href="https://secure.codeproject.com/KB/vista/Vista_TaskDialog_Wrapper.aspx">CodeProject</a> as well. However, if I need to show the simple error messages only, I would implement the simple task dialog emulator like one that is shown in the picture above.</font><br /><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>Postscriptum.</b></font><br /><font style="font-family:Tahoma;font-size:10pt">I will definitely follow the error message guideline in the future and revise the existing error messages in <a href="http://www.datadynamics.com/Products/DDRPT/default.aspx">the product I actively work on</a>.</font>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com1tag:blogger.com,1999:blog-5306024932265403945.post-89849556865399271822009-01-12T20:39:00.005+06:002009-01-12T21:59:16.600+06:00My first experience with Windows 7<p style="font-family:Tahoma;font-size:10pt">Recently Microsoft has knocked out <a href="http://www.microsoft.com/windows/windows-7/default.aspx">Windows 7 beta</a> and published <a href="http://www.microsoft.com/windows/windows-7/beta-download.aspx">the build for testing purposes</a>. I was not excited about the new version of Windows at all. I remember the experience with the first beta release of <a href="http://www.microsoft.com/windows/windows-vista/">Windows Vista</a> - I installed it and then stopped using in 2 or 3 days. The main reasons were - I was not able to install drivers for the sound card, the new interface seemed terrible for me, <a href="http://www.microsoft.com/windows/windows-vista/">Windows Vista</a> seemed working slowly than <a href="http://www.microsoft.com/windows/windows-xp/">Windows XP</a> and so on. As far as I know, in our days Windows XP is still being chosen over Windows Vista for the majority of business computer sales, so I am sure that I am not only person who stopped using Vista once looked at the first beta release. However, for now I had the new motivation to install Windows 7 - I wanted to see whether the product I work on - <a href="http://www.datadynamics.com/Products/DDRPT/default.aspx">Data Dynamics Reports</a> - can be used on Windows 7. This is what I really excited about. In this post I briefly describe the Windows 7 installation experience and the point where I decided to stop using it - yep, again!<br/><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>The Installation</b></font><br /><font style="font-family:Tahoma;font-size:10pt">The installation of Windows 7 is pretty intuitive and requires very few actions from end-user. The thing I loved is my motherboard integrated devices were detected and installed properly. I thought that it would be a problem because the motherboard drivers for Windows XP and Vista are not compatible with the new OS. However, this fact didn't become the problem at all. The only problem with the installation I faced is <a href="http://www.google.ru/search?hl=ru&newwindow=1&q=%22applying+personal+settings%22+hang&btnG=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA&lr=&aq=f&oq=">"applying personal settings hang"</a> during the first run. However, this problem isn't specific for Windows 7 and I managed it by rebooting the machine several times, starting windows 7 in safe mode and then starting it normally. Sounds crazy, but it works:)</font><br/> <br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>The first run.</b></font><br /><font style="font-family:Tahoma;font-size:10pt">During the first run I faced the problem with WinMail service. It used 100% CPU during the first run. I managed it by running Windows 7 in safe mode and erasing WinMail.exe file. Sounds crazy but it works.</font><br/><br /><font style="font-family:Tahoma;font-size:12pt;color:#4F81BD"><b>The end.</b></font><br /><font style="font-family:Tahoma;font-size:10pt">Well, I successfully installed and run Windows 7 and I thought that I probably was wrong and Microsoft did the great job this time and probably I can use Windows 7 as the primary OS. The new OS interface looks great and it is very convenient. Various software is being installed just fine. The idyll finished when I tried to install Visual Studio .NET 2008. I was not able to install it. The setup is run, the first window with choices to install VS.NET, install MSDN and check for the new releases appeared. I selected install VS.NET and nothing happened. The main window closed, no new processes were run. I tried to run VS.NET 2008 setup with administrator privileges, this doesn't help. I tried setting the compatibility mode for setup.exe and this doesn't help as well. Visual Studio .NET 2005 can't be installed as well with the same symptoms. This looks as weird fact for me - Microsoft software can't be installed on Microsoft OS. And indeed I don't want using OS that doesn't allow installing Visual Studio. This is how my experience with Windows 7 has finished...<br/><br />PS. If someone reads this blog and uses Windows 7 beta and was able to install VS.NET 2005(2008) please tell me the secret of the success.</font>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com0tag:blogger.com,1999:blog-5306024932265403945.post-46001172543699055362008-12-22T21:29:00.003+06:002008-12-22T22:58:03.962+06:00WPF - data templating<p style="font-family:Tahoma;font-size:12pt;color:black">Well, I found the weird facts about WPF (at least I think that they are weird) during resolving the first question from the list of the prior post:</p><p style="font-family:Verdana;font-size:12pt;color:black"><i>How to hide the column headers for WPF list view controls?</i></p> <p style="font-family:Verdana;font-size:12pt;color:black">I found no way to disable the column headers for WPF ListView control and no way to disallow the resizing of the columns. However I learned WPF feature called <i><a href="http://msdn.microsoft.com/en-us/library/ms742521.aspx">"data templating"</a></i> which is new for me. Data templating allows you to define the appearance of the items in ListBox and ListView control. Data templating allows you to define the relation between the visual components properties and data source. To achieve my needs (show the data using multicolumn grid view but do not show the column headers) I should use ListBox control specifying the data template for the ListBox items. MSDN shows the examples of the data templates using XAML syntax only, i.e.:<span style="font-size:8pt;color:blue"><br /><ListBox.ItemTemplate><br /> <DataTemplate><br />  <StackPanel><br />   <TextBlock Text="{Binding Path=Name}" /><br />   <TextBlock Text="{Binding Path=Value}"/><br />  </StackPanel><br /> </DataTemplate><br /></ListBox.ItemTemplate></span></span><br /><p class="MsoNormal"> <br />But creating the Data Template programmatically topic looks like somewhat classified. Well, let’s look at this topic closer. ListBox and ListView types have <a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.itemtemplate.aspx">ItemTemplate</a> property which is inherited from <a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.aspx">ItemsControl</a> class which represents a control that can be used to present a collection of items. The type of ItemTemplate property is <a href="http://msdn.microsoft.com/en-us/library/system.windows.datatemplate.aspx">DataTemplate</a> class. DataTemplate overview in MSDN also has only XAML syntax bases examples. DataTemplate class has <a href="http://msdn.microsoft.com/en-us/library/system.windows.frameworktemplate.visualtree.aspx">VisualTree</a> property which should be set to define the appearance of the items. Actually this is not that explicitly stated in MSDN. Then the type of VisualTree property of DataTemplate class is <a href="http://msdn.microsoft.com/en-us/library/system.windows.frameworkelementfactory.aspx">FrameworkElementFactory</a> class. The description of this class says:<br/><br /><i>"This class is a deprecated way to programmatically create templates…not all of the template functionality is available when you create a template using this class. The recommended way to programmatically create a template is to load XAML from a string or a memory stream"</i><br/><br />So, guys in MS believe that creating the data templates programmatically is a deprecated way! It sounds like terrific fact for me. However, I tried to find the limitations that exist for creating the data templates programmatically and instantaneously faced the problem. First of all I tried to create the visual tree for the data template that is shown above (stack panel has 2 child textblocks, the 1st textblock is bound to Name property of data source item, the 2nd textblock is bound to Value property). Operating on FrameWorkElement factory is weird itself. Look at the code: <span style="font-size:8pt;color:blue"><br />private static FrameworkElementFactory CreateDataTemplate()<br />{<br />   var txtNode = new FrameworkElementFactory(typeof(TextBlock)); <br />   txtNode.SetBinding(TextBlock.TextProperty, new Binding("Name"));<br />   var valueNode = new FrameworkElementFactory(typeof(TextBlock));<br />   valueNode.SetBinding(TextBlock.TextProperty, new Binding("Value"));<br />   var stackPanelNode = new FrameworkElementFactory(typeof (StackPanel));<br />   stackPanelNode.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);<br />   stackPanelNode.AppendChild(txtNode);<br />   stackPanelNode.AppendChild(valueNode);<br />   return stackPanelNode;<br />}</span><br />So, to create the visual tree for the data template programmatically I need to manually replicate the corresponding XAML nodes tree in the code and this way has limitations.<br />Let’s return to the goal I wanted to achieve:<br /><i>Show the data using multicolumn grid view but do not show the column headers.</i><br />Basically I need to show the data in ListBox control and define the data template with visual tree that is Grid control:<span style="font-size:8pt;color:blue"><br /><Grid><br /> <Grid.ColumnDefinitions><br />  <ColumnDefinition Width="100" /><br />  <ColumnDefinition Width="50" /><br /> </Grid.ColumnDefinitions><br /> <Grid.RowDefinitions><br />  <RowDefinition /><br /> </Grid.RowDefinitions><br /> <TextBlock Text="{Binding Path=Name}" Grid.Column="0" Grid.Row="0" /><br /> <TextBlock Text="{Binding Path=Value}" Grid.Column="1" Grid.Row="0" /><br /></Grid></span><br />Well, I tried to create this visual tree programmatically:<br /><span style="font-size:8pt;color:blue"><br />private static FrameworkElementFactory CreateDataTemplate()<br />{<br />   var txtNode = new FrameworkElementFactory(typeof(TextBlock));<br />   txtNode.SetBinding(TextBlock.TextProperty, new Binding("Name"));<br />   txtNode.SetValue(Grid.RowProperty, 0);<br />   txtNode.SetValue(Grid.ColumnProperty, 0);<br />   var valueNode = new FrameworkElementFactory(typeof (TextBlock));<br />   valueNode.SetBinding(TextBlock.TextProperty, new Binding("Value"));<br />   valueNode.SetValue(Grid.RowProperty, 0);<br />   valueNode.SetValue(Grid.ColumnProperty, 1);<br />   var rowDefNode = new FrameworkElementFactory(typeof (RowDefinition));<br />   var col1DefNode = new FrameworkElementFactory(typeof (ColumnDefinition));<br />   var col2DefNode = new FrameworkElementFactory(typeof(ColumnDefinition));<br />   var rowsDefNode = new FrameworkElementFactory(typeof (RowDefinitionCollection));<br />   rowsDefNode.AppendChild(rowDefNode);<br />   var colsDefNode = new FrameworkElementFactory(typeof (ColumnDefinitionCollection));<br />   colsDefNode.AppendChild(col1DefNode);<br />   colsDefNode.AppendChild(col2DefNode);<br />   var gridNode = new FrameworkElementFactory(typeof (Grid));<br />   gridNode.AppendChild(rowsDefNode);<br />   gridNode.AppendChild(colsDefNode);<br />   gridNode.AppendChild(txtNode);<br />   gridNode.AppendChild(valueNode);<br />}</span><br />Executing this code throws the following exception:<br /><span style="color:red"><i>"'RowDefinitionCollection' type must derive from FrameworkElement, FrameworkContentElement, or Visual3D."</i></span><br />Yep! You can’t create the visual tree nodes for types which are not derived from the listed types! This is the main limitation of creating data template programmatically. <br />When I faced that I thought that I made some mistake, I thought – well, probably I can load the data template from pre-defined XAML visual tree that is based on Grid definition and look how VisialTree property value is constructed? Nope. If you load the data template from XAML content, then VisualTree property of DataTemplate instance is null.<br />So, the only way to construct the data template programmatically is load it from XAML fragments. I think that this is very weird fact.<br />Indeed I can be asked – why do you need to create the data templates at runtime? Do you know any live use-case of that? Yes, I know.<br />The first idea that came to my mind when I learned the data templates is we can create the simple reporting engine using WPF capabilities. The reporting engine that seems like <a href="http://www.datadynamics.com/Products/ProductFeatures.aspx?Product=ARNET3">ActiveReports</a> would be created very easy. End users would specify the data they want to show and the data item template exactly like <a href="http://www.datadynamics.com/Products/ProductFeatures.aspx?Product=ARNET3&Topic=Designer:%20Easy%20to%20Learn">ActiveReports designer</a>. Then the engine would construct the data template programmatically and show the data in WPF ListBox control. With the current way of operating on Data Templates programmatically this is not possible. <br />Well, once again returning to the problem that I tried to resolve – I made it by using Grid based data template that is loaded from XAML resource file. The code is trivial.<br /></p>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com2tag:blogger.com,1999:blog-5306024932265403945.post-80915766926448316122008-12-14T22:30:00.000+06:002008-12-14T23:32:34.028+06:00WPF - the power of data binding<span style="">During last 2 weeks I was distracted from VS.NET 2010 learning. We prepare the next release of <a href="http://www.datadynamics.com/Products/DDRPT/default.aspx">Data Dynamics Reports</a> and I am totally occupied by coding, code reviewing and testing.<o:p></o:p></span> <p class="MsoNormal" style="line-height: normal;"><span style="">However, one of the tasks I am working on turned me onto looking at <a href="http://en.wikipedia.org/wiki/Windows_Presentation_Foundation">WPF</a> and I would like to write about it here.<o:p></o:p></span></p> <p class="MsoNormal" style="line-height: normal;"><span style="">Well, one of the common tasks in Windows Applications development is presentation of the data. You might want to show SQL Server table data in the <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.datagrid.aspx">DataGrid</a> control or show the list of items that come from <a href="http://www.google.ru/url?sa=t&source=web&ct=res&cd=2&url=http%3A%2F%2Fcode.google.com%2Fapis%2Fgdata%2Foverview.html&ei=cEFFSYS5Bo-C-gbUu7y7Aw&usg=AFQjCNGsqimjvSAlpUz37KBYVRQgeRY5iA&sig2=ob02nm1JgTc45E0qDLde_g">GData</a> sources.<o:p></o:p></span></p> <p class="MsoNormal" style="line-height: normal;"><span style="">I worked on the code which is intended for show the collection of the business objects in such a way that the presentation is multi-column grid view where every column shows the certain business object property value. The collection of business objects may change dynamically – the end user can add the new items, delete the existing items and change the object property values. The presentation has to reflect these changes immediately. The presentation should not provide edit capabilities itself. The rest of UI provides end-users with tools that allow editing the collection.<o:p></o:p></span></p> <p class="MsoNormal" style="line-height: normal;"><span style="">.NET 2.0 Windows Forms include <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.listview.aspx">ListView</a> control which is exactly that I needed – it shows the list of the items and every item can consist of sub-items and every sub-item can be shown in the new column.<o:p></o:p></span></p> <p class="MsoNormal" style="line-height: normal;"><span style="">However, .NET 2.0 <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.listview.aspx">ListView</a> has the great hole – it doesn’t allow data binding. That means:<o:p></o:p></span></p> <ul type="disc"><li class="MsoNormal" style="line-height: normal;"><span style=""> I need to initialize ListView items collection by going through the business object collection, creating <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.listviewitem.listviewsubitem.aspx">ListViewSubItem</a> object for every property value, then creating <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.listviewitem.aspx">ListViewItem</a> for every object, then adding the new items in <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.listview.aspx">ListView</a>.<o:p></o:p></span></li></ul> <ul type="disc"><li class="MsoNormal" style="line-height: normal;"><span style=""> I need to handle the business object collection changes and re-initialize <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.listview.aspx">ListView</a> items.<o:p></o:p></span></li></ul> <ul type="disc"><li class="MsoNormal" style="line-height: normal;"><span style=""> I need to handle the business object properties values changes and reflect them in <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.listview.aspx">ListView</a> control.<o:p></o:p></span></li></ul> <p class="MsoNormal" style="margin-bottom: 0.0001pt; line-height: normal;"><span style="">All these stuff doesn’t seem straightforward, yep? However, .NET 2.0 can’t offer any other solution except of DataGrid control which isn’t suitable in my situation by the number of reasons. <o:p></o:p></span></p> <p class="MsoNormal" style="margin-bottom: 12pt; line-height: normal;"><span style="">Well, I thought – “How did they change the situation in WPF?” I have heard that WPF has the super-awesome-cool data binding capabilities. And I looked at how I can implement my task using WPF. I was impressed. ListView control in WPF supports data binding as any other control. To bind the collection of business object to list view control you just need to ensure that the collection class implements <a href="http://msdn.microsoft.com/en-us/library/system.collections.specialized.inotifycollectionchanged.aspx">INotifyCollectionChanged</a> interface in order to reflect the changes in the collection immediately and <a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx">INotifyPropertyChanged</a> interface in order to reflect the changes in the object properties values. .NET 3.5 provides<a href="http://msdn.microsoft.com/en-us/library/ms668604.aspx"> ObservableCollection<(Of <(T>)>) Class</a> which implements both of interfaces. The code to bind the data to ListView is pretty straightforward. Say I have the following business objects class:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgksGAFvatPq4MZy-Dv5Do65YusZ8HCXIqfAfte8tUHGQwTBoIomA7uHoesgqBpRKGLrkHyNDF04IT6fy4tvkLWI4Qjcy44LKfquJq1LHuQD-arUC-cqjZQBKp2ttEJ0fIAy_849YxSoEk6/s1600-h/BusinessObject.PNG"><img style="cursor: pointer; width: 400px; height: 167px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgksGAFvatPq4MZy-Dv5Do65YusZ8HCXIqfAfte8tUHGQwTBoIomA7uHoesgqBpRKGLrkHyNDF04IT6fy4tvkLWI4Qjcy44LKfquJq1LHuQD-arUC-cqjZQBKp2ttEJ0fIAy_849YxSoEk6/s400/BusinessObject.PNG" alt="" id="BLOGGER_PHOTO_ID_5279696405008247938" border="0" /></a></span><br />To create the collection that is bound to ListView control I use the following code:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEji349BjdxHI4HcOV9s55v1ejPt5ezOy0TVSk0UoxxJoEvZMcWm2ygZNca2n_veyp5dub-EZVFnozaanhs30vNLEwn8nZoYqxKUev0vh5t2MkfcJqb5eDo3J0JRMI40AEYdO8AWG4n7GyB4/s1600-h/Collection.PNG"><img style="cursor: pointer; width: 400px; height: 115px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEji349BjdxHI4HcOV9s55v1ejPt5ezOy0TVSk0UoxxJoEvZMcWm2ygZNca2n_veyp5dub-EZVFnozaanhs30vNLEwn8nZoYqxKUev0vh5t2MkfcJqb5eDo3J0JRMI40AEYdO8AWG4n7GyB4/s400/Collection.PNG" alt="" id="BLOGGER_PHOTO_ID_5279696768706471218" border="0" /></a><br /></p><p class="MsoNormal" style="margin-bottom: 12pt; line-height: normal;"><o:p></o:p></p><span style="line-height: 115%;"></span> <p class="MsoNormal"><span style="font-size:85%;"></span></p><span style="line-height: 115%;">And to bind this collection to list view I use the following code:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_B95LiTXKyfJtYKl1DuAAUAw7mt-hRWrh6H3ofaVhVJnS4wNuHNueG-oJL7GV2-FHDG5Kw-Ig7blbpGabSBnbcpSSY5k3xCI47bxLWmTwX4bJxdv-6zVqo6oKjFGNf-njFAAEGERBf0yL/s1600-h/BindData.PNG"><img style="cursor: pointer; width: 400px; height: 88px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_B95LiTXKyfJtYKl1DuAAUAw7mt-hRWrh6H3ofaVhVJnS4wNuHNueG-oJL7GV2-FHDG5Kw-Ig7blbpGabSBnbcpSSY5k3xCI47bxLWmTwX4bJxdv-6zVqo6oKjFGNf-njFAAEGERBf0yL/s400/BindData.PNG" alt="" id="BLOGGER_PHOTO_ID_5279696974951363442" border="0" /></a><br /></span><p class="MsoNormal"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbWN8N6qOXEiiNdR7Xyv3SPLvDKUBAmiziscDe0qocemwD8M-_qHuCaqCchv2rpu41033plyw51lN9LEAJwKN_L_3o49E5fyS8_oYmau6-3CkFfdccxrmSCH8-5Ss2sPPS-nFqowN0sB2M/s1600-h/BindData.PNG"> </a></p><span style="line-height: 115%;">That’s all! Looks very cool, doesn’t it?<br /><br />After I tried this, the new question came to my mind. I didn't find the obvious solution for them.<br /></span><ul><li>How to hide the column headers for WPF list view controls?<br /></li><li>How to highlight the list view item when the mouse is over it?</li><li>How to set the background for the selected item?</li><li>How to disable the columns resizing capability?</li></ul>Well, I will try to figure it out and write about any interesting:)<br /><span style="line-height: 115%;"><o:p></o:p></span>Mr. Abakumoffhttp://www.blogger.com/profile/17010834775053195314noreply@blogger.com0