Getting Ramped for Silverlight 4

Here is a quick walk through of setting up your Silverlight 4 development environment.  The first assumed step is that you have Visual Studio 2010 already installed and any appropriate patches.  Then download the following in order and install each.

Once each of these are installed jump into Visual Studio 2010.  Start a new Silverlight 4 Project by going to File -> New -> Project -> and select the Silverlight Project Templates.  Here you'll see a new list of projects that are specific to the above listed downloads.

  • Silverlight Business Application
  • WCF RIA Service Class Library
  • Silverlight Unit Test Application

One way to confirm (and what I am going to display here in this entry) Silverlight 4 is installed ok is to select the Silverlight Application Template and start a new project.

On the next screen you will see some of the standard options.  I always go with the ASP.NET MVC Option and with these new installations I am going to select Silverlight 4 (should be selected already) from the drop down and check the Enable WCF RIA Services check box.

I also, for good measure, always create a unit test project for the ASP.NET MVC Project that will host the Silverlight Application Project.  When all is setup, the Solutions Explorer should look like what is shown below.

Add the following code to the XAML of the MainPage.xaml of the Silverlight Project.

<UserControl x:Class="Silverlight4.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
 
    <Grid x:Name="LayoutRoot" Background="White">
        <TextBlock x:Name="textBlockTest" Text="Hello World!" />
    </Grid>
</UserControl>

Now execute the project, if all runs well you have installed Silverlight 4 successfully.

Bam!  Silverlight 4 ready to go!  I will have more on Silverlight 4 very soon, as I will be starting a project (personal) and blogging it as I work through it.  Also, if you run into any issues I would like to read about them, so please comment.  I had a few issues and also had some design time rendering issues in the VS 2010 IDE when I installed these bits at first.

kick it on DotNetKicks.com Shout it
Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Posted by: Adron
Posted on: 4/26/2010 at 2:18 PM
Tags: , ,
Categories: How-To, Samples, and Such
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (2) | Post RSSRSS comment feed

Blending the Sketchflow Action

Started a new Sketchflow Prototype in Expression Blend recently and documented each of the steps.  This blog entry covers some of those steps, which are the basic elements of any prototype.  I will have more information regarding design, prototype creation, and the process of the initial phases for development in the future.  For now, I hope you enjoy this short walk through.  Also, be sure to check out my last quick entry on Sketchflow.

I started off with a Sketchflow Project, just like I did in my previous entry (more specifics in that entry about how to manipulate and build out the Sketchflow Map).

Once I created the project I setup the following Sketchflow Map.

The CoreNavigation is a ComponentScreen setup solely for the page navigation at the top of the screen.  The XAML markup in case you want to create a Component Screen with the same design is included below.

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:pb="clr-namespace:Microsoft.Expression.Prototyping.Behavior;assembly=Microsoft.Expression.Prototyping.Interactivity"
    x:Class="RapidPrototypeSketchScreens.CoreNavigation"
    d:DesignWidth="624" d:DesignHeight="49" Height="49" Width="624">
 
    <Grid x:Name="LayoutRoot">
        <TextBlock HorizontalAlignment="Stretch" Margin="307,3,0,0" Style="{StaticResource TitleCenter-Sketch}" Text="A?t?chart Scorecards" TextWrapping="Wrap">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseLeftButtonDown">
                    <pb:NavigateToScreenAction TargetScreen="RapidPrototypeSketchScreens.Screen_1"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </TextBlock>
        <Button HorizontalAlignment="Left" Margin="164,8,0,11" Style="{StaticResource Button-Sketch}" Width="144" Content="Scorecard">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <pb:NavigateToScreenAction TargetScreen="RapidPrototypeSketchScreens.Screen_1_2"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
        <Button HorizontalAlignment="Left" Margin="8,8,0,11" Style="{StaticResource Button-Sketch}" Width="152" Content="Standard Reports">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <pb:NavigateToScreenAction TargetScreen="RapidPrototypeSketchScreens.Screen_1_1"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>
    </Grid>
</UserControl>

Now that the CoreNavigation Component Screen is done I built out each of the others.  In each of those screens I included the CoreNavigation Screen (all those little green lines in the image) as the top navigation.  In order to do that, as I created each of the pages I would hover over the CoreNavigation Object in the Sketchflow Map.  When the utilities drawer (the small menu that pops down under a node when you hover over it) shows click on the third little icon and drag it onto the page node you want a navigation screen on.

Once I created all the screens I setup the navigation by opening up each screen and right clicking on the objects that needed to point to somewhere else in the prototype.

Once I was done with the main page, my Home Navigation Page, it looked something like this in the Expression Blend Designer.

I fleshed out each of the additional screens.  Once I was done I wanted to try out the deployment package.  The way to deploy a Sketchflow Prototype is to merely click on File ?> Package SketchFlow Project and a prompt will appear.  In the prompt enter what you want the package to be called.

I like to see the files generated afterwards too, so I checked the box to see that.  When Expression Blend is done generating everything you?ll have a directory like the one shown below, with all the needed files for deployment.

Now these files can be copied or moved to any location for viewing.  One can even copy them (such as via FTP) to a server location to share with others.  Once they are deployed and you run the "TestPage.html" the other features of the Sketchflow Package are available.

In the image below I have tagged a few sections to show the Sketchflow Player Features.  To the top left is the navigation, which provides a clearly defined area of movement in a list.  To the center right is the actual prototype application.  I have placed lists of things and made edits.  On the left hand side is the highlight feature, which is available in the Feedback section of the lower left.  On the right hand list I underlined the Autochart with an orange marker, and marked out two list items with a red marker.

In the lower left hand side in the Feedback section is also an area to type in your feedback.  This can be useful for time based feedback, when you post this somewhere and want people to provide subsequent follow up feedback.

Overall lots of great features, that enable some fairly rapid prototyping with customers.  Once one is familiar with the steps and parts of this Sketchflow Prototype Capabilities it is easy to step through an application without even stopping.  It really is that easy.  So get hold of Expression Blend 3 and get ramped up on Sketchflow, it will pay off in the design phases to do so!

kick it on DotNetKicks.com Shout it
Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Posted by: Adron
Posted on: 4/16/2010 at 7:25 PM
Tags: , ,
Categories: How-To, Samples, and Such | UI Design | Keeping Up
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (1) | Post RSSRSS comment feed

Part 1 Basic Webtrends REST Examples

In this entry I just want to cover some examples of how to connect to Webtrends DX Web Services.  The DX Web Services use REST as the architecture, providing simple URI based end points to connect to.  With the Webtrends SDK you can connect to these services with your account information.  Here are the basic steps to retrieve a profile list, the reports from one of those profiles, and then the report you want from that report list.

First step is to create a Webtrends User.

WebTrends.Sdk.Account.User webtrendsUser = new Account.User();
webtrendsUser.UserName = username;
webtrendsUser.Password = password;
webtrendsUser.AccountName = account;

After you create the Webtrends User, simple request a profile list by getting list of ProfileDefinition Objects.

List<WebTrends.Sdk.Profile.ProfileDefinition> profiles = 
  WebTrends.Sdk.Factory.NavigationFactory.BuildListing(webtrendsUser);

Next you will want to grab a report based on the profile you are in and your credentials.

List<WebTrends.Sdk.Report.ReportDefinition> reports = 
WebTrends.Sdk.Factory.NavigationFactory.BuildListing(profiles[i], webtrendsUser);

In the code above, i would equate to the specific profile you want from the retrieved list of profiles in the profiles list.  The common scenario is that one has pulled the profiles into a drop down, combo, or list box that the user can select.  Then when the user selects the specific profile that profile object can then be used to pull the List of ReportDefinitions.

Once we have the report definitions, all sorts of criteria can be added together to query for a specific report.  This is also were things can get a little tricky.  For instance, take a look at the code below.

WebTrends.Sdk.Factory.ReportFactory.CreateDimensionalReport(
    report.ID.ToString(), profiles[i].ID.ToString(), "2010m01", webtrendsUser);

The CreateDimensionalReport takes 4 parameters for this particular overload.  The report ID, profile ID, the Webtrends Date Format, and the Webtrends User Object.  There are a number of other overloads available within this factory's method that allow for passing the specific REST URI, and other criteria to retrieve the report of your choice.  In the near future we will be adding some more to this method also, which will provide more flexibility without needing to use the full REST URI.

I will have more on this, so all you Coders out there using Webtrends DX Services, I hope this is helpful!  Enjoy.

Shout it kick it on DotNetKicks.com
Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Posted by: Adron
Posted on: 4/14/2010 at 5:20 PM
Tags: , , , ,
Categories: WebTrends | How-To, Samples, and Such
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

Styles for XAML (Silverlight & WPF)

This is a quick walk through of how to setup things for skinning within a XAML Application.  First thing, find the App.xaml file within the WPF or Silverlight Project.

Within the App.xaml file set some default styles for your controls.  I set the following for a button, label, and border control for an application I am creating.

Button Control

<Style x:Key="ButtonStyle" TargetType="Button">
    <Setter Property="FontFamily" Value="Arial" />
    <Setter Property="FontWeight" Value="Bold" />
    <Setter Property="FontSize" Value="14" />
    <Setter Property="Width" Value="180" />
    <Setter Property="Height" Value="Auto" />
    <Setter Property="Margin" Value="8" />
    <Setter Property="Padding" Value="8" />
    <Setter Property="Foreground" Value="AliceBlue" />
    <Setter Property="Background" >
        <Setter.Value>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="Black" Offset="0" />
                <GradientStop Color="#FF5B5757" Offset="1" />
            </LinearGradientBrush>
        </Setter.Value>
    </Setter>
</Style>

Label Control

<Style x:Key="LabelStyle" TargetType="Label">
    <Setter Property="Width" Value="Auto"/>
    <Setter Property="Height" Value="28" />
    <Setter Property="Foreground" Value="Black"/>
    <Setter Property="Margin" Value="8"/>
</Style>

Border Control

<Style x:Key="BorderStyle" TargetType="Border">
    <Setter Property="BorderThickness" Value="4"/>
    <Setter Property="Width" Value="Auto"/>
    <Setter Property="Height" Value="Auto" />
    <Setter Property="Margin" Value="0,8,0,0"/>
    <Setter Property="CornerRadius" Value="18"/>
    <Setter Property="BorderBrush">
        <Setter.Value>
            <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
                <GradientStop Color="CornflowerBlue" Offset="0" />
                <GradientStop Color="White" Offset="1" />
            </LinearGradientBrush>
        </Setter.Value>
    </Setter>
</Style>

These provide good examples of setting individual properties to a default, such as;

<Setter Property="Width" Value="Auto"/>
<Setter Property="Height" Value="Auto" />

Also for settings a more complex property, such as with a LinearGradientBrush;

<Setter Property="BorderBrush">
    <Setter.Value>
        <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
            <GradientStop Color="CornflowerBlue" Offset="0" />
            <GradientStop Color="White" Offset="1" />
        </LinearGradientBrush>
    </Setter.Value>
</Setter>

These property setters should be located between the opening and closing <Application.Resources></Application.Resources> tags.

<Application x:Class="ScorecardAndDashboard.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
    </Application.Resources>
</Application>

Now in the pages, user controls, or whatever you are marking up with XAML, for the Style Property just set a StaticResource such as shown below.

     <!-- Border Control -->
<Border Name="borderPollingFrequency" Style="{StaticResource BorderStyle}">
     <!-- Label Control -->
<Label Content="Trigger Name:" Style="{StaticResource LabelStyle}"></Label>
     <!-- Button Control -->
<Button Content="Save Schedule" Name="buttonSaveSchedule"  Style="{StaticResource ButtonStyle}" HorizontalAlignment="Right"/>

That's it.  Simple as that.  There are other ways to setup resource files that are separate from the App.xaml, but the App.xaml file is always a good quick place to start.  As moving the styles to a specific resource file later is a mere copy and paste.

Shout it kick it on DotNetKicks.com
Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Posted by: Adron
Posted on: 3/22/2010 at 4:53 PM
Categories: How-To, Samples, and Such | UI Design
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (6) | Post RSSRSS comment feed

Getting The Bits Swinging in the Business

Read Part 1 & Part 2 of this series if you haven't already. 

Last entry I worked up the basic origins and destinations for the data we have. Now we have to start turning this into something real, something concrete. The following processes include a whole soup of acronyms and other cryptic vocabulary. The most common thing I will probably use is the ETL acronym, which stands for Extract, Transform, and Load. This is the process of bridging the data to the various originations and destination and moving that data appropriately.

In the last entry I finalized the originations and destinations as shown below;

Originations
Excel & Access (Office 2007) *.mdb, *.xlsx, and *.csv/*.txt data stores
Internal Account Software (IAS) This one is a prospective can of worms.  Proprietary layouts, de-normalized & normalized data, and all sorts of redundant, non-atomic data.  This sounds like an accounting package right?  :p
Webtrends Analytics Data Exchange Web Services (DX) Webtrends web services provide REST style architecture, with the ability for data to be retrieved in XML, JSON, HTML, or other formats (we can add more if need be, just let us know).
Point of Sale System (POS) This system provides two daily exports, one at 6:00am and one at noon for processing.  The export format is *.csv.

Destination
SSRS SQL Server Reporting Services, with the core underlying data stored in SQL Server.

In my previous entry you may have noticed that I had posted SSIS with the Destination list.  Being one that corrects themselves when mistaken, I took it out, as it does not belong there.  The SSIS is our tool that will perform the ETL functionality for this project.

At this point we are finally going to get into the dirty bits of these pieces of technology, and how we need to tie them together.  I am going to attack them over the next few entries based on the order in the lists above.  The first item, is the Excel & Access 2007 customer relations listings from sales.  Here?s a description and a few shots of what this thing looks like.

The access database is setup with a very simple relational data schema.  This is shown below (click image for larger view).

You can see there are pretty standard pieces of data, in a generally normalized (3rd form for the most part) structure.  This is fine.

Next is a shot of the data entry screen for adding opportunities.  There are respective screens for customers and employees.  Everything needed for a basic customer list & tracking basic things.  Nothing too extravagant here either.  Again, all is fine.

Below is a simple report that shows the available opportunities that are open.

Another report showing the forecasts.

Below is another forecast sliced grid.

So all that seems normal enough.  But the processes are what makes things tricky.  If everyone just managed sales from the database, all would be right in the world.  The first thing that breaks this is that each sales person enters their sales during the day and other information in a spreadsheet that is not linked to the underlying database.  Someone each morning puts the previous days sales information.  This of course, breaks down data integrity.  Below is a sample sheet that is used each day.

One thing that Excel is used for, that doesn?t break reports is the lists of prospective customers to call.  As shown below.

Now that we have a break down of the Excel & Access Customer Relations Management Software, I will move onto the other pieces of technology in the next entry.  This is the data point that has the most prospective data risk, so I put it at the top of the list to cover first.  After I cover each of the systems, we will move into the architecture of the system overall.  So keep reading, more juicy bits to come.

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Encryption and Decryption Code Bits

I recently had to do some simple encryption and decryption for password storage.  I wanted to document this so a blog entry seemed in order.  So without any yammering here's the simple class I created.

public static class EncryptionHelper
    {
        private const string CryptographyKey = "CryptKey";
 
        // The Initialization Vector for the DES encryption routine
        private static readonly byte[] iv =
            new byte[] { 220, 13, 41, 29, 1, 63, 73, 9 };
 
        /// <summary>
        /// Encrypts provided string parameter
        /// </summary>
        public static string Encrypt(string s)
        {
            if (string.IsNullOrEmpty(s)) return string.Empty;
 
            byte[] buffer = Encoding.ASCII.GetBytes(s);
            var des = new TripleDESCryptoServiceProvider();
            var md5 = new MD5CryptoServiceProvider();
 
            des.Key = md5.ComputeHash(Encoding.ASCII.GetBytes(CryptographyKey));
            des.IV = iv;
 
            string result = Convert.ToBase64String(
                des.CreateEncryptor().TransformFinalBlock(
                    buffer, 0, buffer.Length));
 
            return result;
        }
 
        /// <summary>
        /// Decrypts provided string parameter
        /// </summary>
        public static string Decrypt(string s)
        {
            if (string.IsNullOrEmpty(s)) return string.Empty;
 
            byte[] buffer = Convert.FromBase64String(s);
            var des = new TripleDESCryptoServiceProvider();
            var md5 = new MD5CryptoServiceProvider();
 
            des.Key = md5.ComputeHash(Encoding.ASCII.GetBytes(CryptographyKey));
            des.IV = iv;
 
            string result = Encoding.ASCII.GetString(
                des.CreateDecryptor().TransformFinalBlock(
                    buffer, 0, buffer.Length));
 
            return result;
        }
    }

So simple enough.  Hope that is helpful to anyone interested in a super easy encrypt & decrypt example.  : )

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Posted by: Adron
Posted on: 1/15/2010 at 5:33 AM
Tags: , ,
Categories: How-To, Samples, and Such
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

ASP.NET MVC Scorecard Web Application - Part 3

In this entry I want to cover a helper I wrote and some other bits to simplify creating charts for the scorecard application.

One of the things I wanted to do was get rid of the excessive amount of code needed in the view to generate various charts.  Since at some point I wanted to be able to dynamically create charts based on user input, I figured what better time than now to start chiseling out a helper class for displaying the charts.

Take the pie chart I created in the last entry.  The code in the view looked like this.

using (Chart chartPie = new Chart())
{
    double[] yValues = (double[])ViewData["TopCountryCounts"];
    string[] xValues = (string[])ViewData["TopCountries"];
 
    Title t = new Title("Pie Chart Representation",
        Docking.Top,
        new System.Drawing.Font("Verdana, Helvetica, Sans-Serif", 14, System.Drawing.FontStyle.Bold),
        System.Drawing.Color.FromArgb(26, 59, 105));
    chartPie.Titles.Add(t);
    chartPie.ChartAreas.Add("Default");
 
    // create a couple of series
    chartPie.Series.Add("Default");
    chartPie.Series["Default"].Points.DataBindXY(xValues, yValues);
 
    // Set Doughnut chart type
    chartPie.Series["Default"].ChartType = SeriesChartType.Pie;
 
    // Set labels style
    chartPie.Series["Default"]["PieLabelStyle"] = "Inside";
    // Set Doughnut radius percentage
    chartPie.Series["Default"]["DoughnutRadius"] = "40";
    // Explode data point with label "USA"
    chartPie.Series["Default"].Points[3]["Exploded"] = "true";
 
    chartPie.Width = 400;
    chartPie.Height = 300;
    chartPie.Page = this;
    HtmlTextWriter writer = new HtmlTextWriter(Page.Response.Output);
    chartPie.RenderControl(writer);
}

At 31 lines of code, I was not really stoked about this.  A lot of this, such as creating the title, the chart area, and having a series was something that would be needed by most charts.  With that I went to work writing a set of tests to test the helper class.

public const string title = "Chart Title";
public double[] YValues = {3};
public string[] XValues = {"X Value"};
 
[TestMethod]
public void InstantiateChartHelper()
{
    ChartHelper chartHelper = new ChartHelper("title", YValues, XValues, SeriesChartType.Pie);
    Assert.IsNotNull(chartHelper);
}

This first test and default values, that I assumed I would use for the other tests, got me a nice skeleton class & constructor.  I used ReSharper to flesh it out a little and then went to writing the other tests.  Each contributing a bit more functionality to the overall class.  I have excluded the remaining tests from this blog entry, but they will be available when I provide the solution for download (that means keep reading and stay tuned).  The class however, that ended up with is below.

public class ChartHelper
{
    public ChartHelper(string chartTitle, IEnumerable<double> seriesValues, IEnumerable<string> seriesKeys, SeriesChartType chartType)
    {
        // Setup defaults.
        System.Drawing.Font font = new System.Drawing.Font("Verdana, Helvetica, Sans-Serif", 14, System.Drawing.FontStyle.Bold);
        System.Drawing.Color color = System.Drawing.Color.FromArgb(26, 59, 105);
 
        // Title
        Title title = new Title(chartTitle, Docking.Top, font, color);
       
        // Chart Area
        ChartArea chartArea = new ChartArea("DefaultChartArea");
        chartArea.Area3DStyle.Enable3D = true;
        
        // Series
        Series series = new Series("DefaultSeries");
        series.Points.DataBindXY(seriesKeys, seriesValues);
        series.ChartType = chartType;
 
        ResultingChart = new Chart();
        ResultingChart.Titles.Add(title);
        ResultingChart.ChartAreas.Add(chartArea);
        ResultingChart.Series.Add(series);
        
    }
 
    public Chart ResultingChart { get; set; }
}

As you can see, a nice simple class.  With this class I was then able to use to reduce my lines of code to 9 lines (including the multi-line instantiation, which I suppose could be one line, leaving me with 6).

Scorecard.Views.ChartHelper chartHelper = new Scorecard.Views.ChartHelper("Pie Chart Representation",
   (double[])ViewData["TopCountryCounts"],
   (string[])ViewData["TopCountries"],
   SeriesChartType.Pie);
Chart chartPieTwo = chartHelper.ResultingChart;
 
chartPieTwo.Page = this;
HtmlTextWriter writer1 = new HtmlTextWriter(Page.Response.Output);
chartPieTwo.RenderControl(writer1);

This now generates the following pie chart.

There are a few more defaults I want to set though, so I went ahead and added a logic section for pie charts as shown below, with the switch view to provide a bit of factory style magic.

ResultingChart = new Chart();
 
// Setup defaults.
System.Drawing.Font font = new System.Drawing.Font("Verdana, Helvetica, Sans-Serif", 14, System.Drawing.FontStyle.Bold);
System.Drawing.Color color = System.Drawing.Color.FromArgb(26, 59, 105);
 
// Title
Title title = new Title(chartTitle, Docking.Top, font, color);
ResultingChart.Titles.Add(title);
 
// Chart Area
ChartArea chartArea = new ChartArea("DefaultChartArea") {Area3DStyle = {Enable3D = true}};
ResultingChart.ChartAreas.Add(chartArea);
 
// Series
Series series = new Series("DefaultSeries");
series.Points.DataBindXY(seriesKeys, seriesValues);
series.ChartType = chartType;
ResultingChart.Series.Add(series);
 
// Legend
Legend legend = new Legend("DefaultLegend");
ResultingChart.Legends.Add(legend);
 
switch (chartType)
{
    case SeriesChartType.Bar:
        break;
    case SeriesChartType.Column:
        break;
    case SeriesChartType.Pie:
        series["PieLabelStyle"] = "Inside";
        ResultingChart.Legends[0].Docking = Docking.Bottom;
        ResultingChart.Legends[0].Enabled = true;
        break;
    case SeriesChartType.Funnel:
        break;
    case SeriesChartType.Line:
        break;
    default:
        throw new ArgumentOutOfRangeException("chartType");
}
 
ResultingChart.Width = 400;
ResultingChart.Height = 300;

Notice I also reorganized where some things where instantiated, such as the Chart Object, and organized the order according to each thing I needed to have for the chart.  Once I did this I ran and rendered the chart, which I was happy with for now.

At this point I went back in and added some more charts to my scorecard view.  While I did this I noticed one last thing I ought to refactor.

<table>
<tr>
<td>
    <%
        Scorecard.Views.ChartHelper chartHelper = new Scorecard.Views.ChartHelper("Top Countries",
           (double[])ViewData["TopCountryCounts"],
           (string[])ViewData["TopCountries"],
           SeriesChartType.Pie);
        Chart chartPieTwo = chartHelper.ResultingChart;
 
        // Explode data point with label "USA"
        chartPieTwo.Series["DefaultSeries"].Points[3]["Exploded"] = "true";
 
        chartPieTwo.Page = this;
        HtmlTextWriter writer = new HtmlTextWriter(Page.Response.Output);
        chartPieTwo.RenderControl(writer);
    %>
</td>
<td>
    <%
        chartHelper = new Scorecard.Views.ChartHelper("View Cart Trend",
           (double[])ViewData["LineValues"],
           (string[])ViewData["TopEngines"],
           SeriesChartType.Line);
 
        Chart lineChart = chartHelper.ResultingChart;
 
        lineChart.Page = this;
        lineChart.RenderControl(writer);
    %>
</td>
</tr>
<tr>
<td>
    <%
        chartHelper = new Scorecard.Views.ChartHelper("Yesterday's Page Views",
         (double[])ViewData["ColumnStats"],
         (string[])ViewData["ColumnStatHeaders"],
         SeriesChartType.Column);
 
        Chart columnChart = chartHelper.ResultingChart;
 
        columnChart.Page = this;
        columnChart.RenderControl(writer);
    %>
</td>
<td>
    <%
        double[] theValues = (double[]) ViewData["ColumnStats"];
        double[] newValues = new double[]{0,0,0,0};
        int count = 0;
        foreach(double d in theValues)
        {
            newValues[count] += d*DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month) +
                                DateTime.Now.Month + DateTime.Now.Millisecond;
            
            count++;
        }
 
        chartHelper = new Scorecard.Views.ChartHelper("Current Month Page Views",
    newValues,
    (string[])ViewData["ColumnStatHeaders"],
    SeriesChartType.Bar);
 
        Chart barChart = chartHelper.ResultingChart;
 
        barChart.Page = this;
        barChart.RenderControl(writer);
    %>
</td>
</tr>
</table>

I was assigning the page and rendering the control at every single section within my table.  I didn't need to do that, so I went back and added a render method to the ChartHelper Class.

public void RenderChart(Page page)
{
    ResultingChart.Page = page;
    HtmlTextWriter writer = new HtmlTextWriter(page.Response.Output);
    ResultingChart.RenderControl(writer);
}

With a small change to the view I can now render each chart with one line of code.

chartHelper.RenderChart(this);

Now that puts everything in a better situation.  Until the next part.  Happy coding.

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Posted by: Adron
Posted on: 1/6/2010 at 5:02 AM
Tags: , , , , ,
Categories: How-To, Samples, and Such
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (3) | Post RSSRSS comment feed

ASP.NET MVC Scorecard Web Application - Part 2

Alright, time to add some actual functionality to this thing.  First I want a report showing up on the scorecard page that has already been created.  I don't really care what it displays, just want to get it working and displaying.  I will get one report working and then pull up others and connect them with actual data from the Model.

First things first I grabbed the MS Charting controls, which you will need to follow along with this section of code.  I assume for the rest of this entry that the charting controls are installed.

First off I created some nice fake data in a DataTable.  The object I created is below.  This is located in the Models path for now.  Just to get this mocked up.

public class ReportSampleData
{
    public ReportSampleData()
    {
        SampleData = new DataTable("Adron's Sample Data");
 
        SampleData.Columns.Add(new DataColumn("Col1"));
        SampleData.Columns.Add(new DataColumn("Col2"));
        SampleData.Columns.Add(new DataColumn("Col3"));
        SampleData.Columns.Add(new DataColumn("Col4"));
 
        DataRow dr1 = SampleData.NewRow();
        dr1[0] = "Sample Set 1";
        dr1[1] = 14;
        dr1[2] = 13;
        dr1[3] = 10;
        DataRow dr2 = SampleData.NewRow();
        dr2[0] = "Sample Set 2";
        dr2[1] = 15;
        dr2[2] = 13;
        dr2[3] = 12;
        DataRow dr3 = SampleData.NewRow();
        dr3[0] = "Sample Set 2";
        dr3[1] = 17;
        dr3[2] = 11;
        dr3[3] = 9;
 
        SampleData.Rows.Add(dr1);
        SampleData.Rows.Add(dr2);
        SampleData.Rows.Add(dr3);
    }
 
    public DataTable SampleData { get; set; }
}

Once I created the fake data, I dropped in the chart control into the Display.aspx view under the Scorecard Directory of the views.

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>
 
<%@ Register Assembly="System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    Namespace="System.Web.UI.DataVisualization.Charting" TagPrefix="asp" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Scorecard
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <form id="form1" runat="server">
    <h2>
        Scorecard
    </h2>
    <%
        using (Chart chartColumns = new Chart())
        {
            chartColumns.Width = 412;
            chartColumns.Height = 296;
            chartColumns.RenderType = RenderType.ImageTag;
           
            chartColumns.Palette = ChartColorPalette.None;
            Title t = new Title("Column Bar Chart",
                Docking.Top,
                new System.Drawing.Font("Verdana, Helvetica, Sans-Serif", 14, System.Drawing.FontStyle.Bold),
                System.Drawing.Color.FromArgb(26, 59, 105));
            chartColumns.Titles.Add(t);
            chartColumns.ChartAreas.Add("Series 1");
 
            // create a couple of series  
            chartColumns.Series.Add("Series 1");
            chartColumns.Series.Add("Series 2");
 
            // add points to series 1  
            foreach (int value in (List<int>)ViewData["Chart"])
            {
                chartColumns.Series["Series 1"].Points.AddY(value + DateTime.Now.Second);
            }
 
            // add points to series 2  
            foreach (int value in (List<int>)ViewData["Chart"])
            {
                chartColumns.Series["Series 2"].Points.AddY(value + DateTime.Now.Minute);
            }
           
            chartColumns.Legends.Add("Legend1");
            chartColumns.BorderSkin.SkinStyle = BorderSkinStyle.None;
            
            // Render chart control  
            chartColumns.Page = this;
            HtmlTextWriter writer = new HtmlTextWriter(Page.Response.Output);
            chartColumns.RenderControl(writer);
        }
    %>
    </form>
</asp:Content>

Once that was finished the final step is to toss in the controller the view data.

public ActionResult Display()
{
    ViewData["Chart"] = new List<int>() {4, 6, 12, 3, 11};
    return View("Display");
}

Now run the app and check out the page.  You should see a chart like that shown below.  (Click for larger image)

That covers the second part of this series.  I will have another addition up soon, tying even more bits together.

Shout it kick it on DotNetKicks.com
Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Posted by: Adron
Posted on: 12/31/2009 at 5:06 AM
Tags: , , , , ,
Categories: How-To, Samples, and Such
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (12) | Post RSSRSS comment feed

ASP.NET MVC Scorecard Web Application - Part 1

There have been a lot of requests for MVC based scorecards, so I am going to kick off a new series of wiring up an MVC scorecard site.  This first part will simply cover setting up the basic site and skeleton framework using the default ASP.NET MVC Project.

Start off by starting a new ASP.NET MVC Project.  Since I will be creating tests for this walk through, be sure to add a unit test project also.  I am just using the default MS-test libraries for now, but feel free to apply whatever test framework you would like.

To create additional views and controllers we'll add a unit test for a new controller.  I will name this new controller ScorecardController, so I have added a test file called ScorecardControllerTest.cs.  The first test is just the standard action for the appropriate method actions and returning the view, as follows.  I added a similar test for the Index method also.

[TestClass]
public class ScorecardControllerTest
{
    [TestMethod]
    public void Scorecard()
    {
        ScorecardController scorecardController = new ScorecardController();
        var result = scorecardController.Scorecard() as ViewResult;
        Assert.IsNotNull(result);
    }
 
    [TestMethod]
    public void Index()
    {
        ScorecardController scorecardController = new ScorecardController();
        var result = scorecardController.Index() as ViewResult;
        Assert.IsNotNull(result);
    }
}

Once the skeleton implementation is made to get green lights on these tests, a controller will be created with the following code.

public class ScorecardController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
 
    public ActionResult Scorecard()
    {
        return View();
    }
}

At this point I need to create some tests for what is expected in the view, but I will get to that once a bit more of the skeleton of the site is done.  As soon as I wrote these tests, based on where they are located in my folder structure I decided that I need to do a quick refactor of the name.  Having a Scorecard/Scorecard path just seemed stupid, so I renamed the Scorecard.aspx to Display.aspx and changed the method name appropriately.  If you are following along, the subsequent code will be using the renamed page/method, etc.

The next thing I wanted to do was to get the view coming up appropriately, so first things first, new tests.

[TestMethod]
public void ScorecardViewExists()
{
    ScorecardController scorecardController = new ScorecardController();
    var result = scorecardController.Display() as ViewResult;
    Assert.AreEqual("Display", result.ViewName);
}

First of course it fails, but with the appropriate change shown, all runs green again.

public ActionResult Display()
{
    return View("Display");
}

So after this I added the following tests, controller actions, and views.

[TestMethod]
public void Select()
{
    ScorecardController scorecardController = new ScorecardController();
    var result = scorecardController.Select() as ViewResult;
    Assert.IsNotNull(result);
}
 
[TestMethod]
public void SelectViewNamed()
{
    ScorecardController scorecardController = new ScorecardController();
    var result = scorecardController.Select() as ViewResult;
    Assert.AreEqual("Select", result.ViewName);
}
 
[TestMethod]
public void IndexViewNamed()
{
    ScorecardController scorecardController = new ScorecardController();
    var result = scorecardController.Index() as ViewResult;
    Assert.AreEqual("Index", result.ViewName);
}

After that I edited the CSS so I could get a better feel to the site relative to what I am working toward.  I will leave you to decide what you want to do with the CSS & such yourself.  One of these days I will be graphic artists worthy, for now I am just happy with a decent looking layout and reasonable colors. ;)

When I was done my Solution Explorer looked like this.

Last I added the following to the Site.Master page for appropriate linkages.  This spot is located in the menucontainer section of the page.

<div id="menucontainer">
    <ul id="menu">
        <li>
            <%= Html.ActionLink("Home", "Index", "Home")%></li>
        <li>
            <%= Html.ActionLink("About", "About", "Home")%></li>
        <li>
            <%= Html.ActionLink("Scorecard", "Display", "Scorecard") %></li>
    </ul>
</div>

When I run the app I now have a basic skeleton and the initial pages I am going to work with.  Next steps coming soon.

kick it on DotNetKicks.com Shout it
Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Posted by: Adron
Posted on: 12/29/2009 at 5:05 AM
Tags: , , , , , ,
Categories: How-To, Samples, and Such | Unit Testing
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (6) | Post RSSRSS comment feed

Charts ala visiFire

As mentioned in my last blog entry, I have been on the hunt for some good charting displays.  I found visifire and here is the quick setup & display of some initial reports.  I used some sample data via trusty Webtrends Analytics 9 API, since we have a bit of example data about the office. ; )

Before even getting started, I am using Visual Studio 2010 beta2.  If you don't have access to this then your screen shots will appear a good bit different then mine, or simply you will not have the same screens I do at all.

First I downloaded the files needed.  The zip with the assemblies has the following files.

  • GPL v3.txt and License.txt are text files about the respective licensing of the charting assemblies.
  • Bin - This folder has the actual assemblies for Silverlight and WPF.
  • Samples - This folder has, simply, samples in it.

Within the Bin folder there are four files.

I'm not really keen on their naming conventions, as the naming seems to be here or there, but it is easily understood.  I would rather just see something along the lines of Visifire.Charts.Sl.dll and Visifire.Charts.Wpf for instance.  But hey, one should not complain, these controls are awesome.

Next I added the assembly to another folder within the project I intend to use the charts in.  In this particular case, the project is a WPF Project, so I am just adding the WPF assembly.

Once you add the assembly make a reference to that assembly the way you would normally make the reference.

Now that we have the appropriate assemblies referenced we?ll throw some basic reports into a WPF User Control.  The next part of this process is were things get a little interesting.  Our next step is to go back out to the visifire site and use the report designer.  When you navigate to the report designer you will see this view.

Over on the left hand side of the designer there are various properties for the reports;  Chart, Data, Title, PlotArea, Legend, TendLine, AxisY, AxisX, AxisLables, ChartGrid, Tick, and Events.  Just below those menu items there is a radio button to select Silverlight or WPF.  Click on the WPF radio button.

I enabled a few others options.  For a complete duplication of the changes I made, check out the XAML snippet below.  I made some changes after the initial designer work was done.  My best practice is to set the basic report, a few data points, and then start working with it in Design Time & XAML view in VS 2010.  Otherwise the designer may redraw something and you want have an undo option.

 <vc:Chart xmlns:vc="clr-namespace:Visifire.Charts;assembly=WPFVisifire.Charts" 
                  Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2"
                  Height="300" BorderThickness="0" Theme="Theme3" View3D="True" AnimationEnabled="True" ColorSet="VisiBlue" LightingEnabled="True"   >
            <vc:Chart.Titles>
                <vc:Title Text="Visit Trending" FontSize="16" FontStretch="SemiCondensed" FontWeight="Bold" TextAlignment="Center" />
            </vc:Chart.Titles>
            <vc:Chart.AxesY>
                <vc:Axis Title="Total Visits" AxisType="Primary" />
            </vc:Chart.AxesY>
            <vc:Chart.Series>
                <vc:DataSeries RenderAs="Column" AxisYType="Primary" >
                    <vc:DataSeries.DataPoints>
                        <vc:DataPoint AxisXLabel="1/1/08" YValue="351139" />
                        <vc:DataPoint AxisXLabel="2/1/08" YValue="345254" />
                        <vc:DataPoint AxisXLabel="3/1/08" YValue="318845" />
                        <vc:DataPoint AxisXLabel="4/1/08" YValue="274316" />
                        <vc:DataPoint AxisXLabel="5/1/08" YValue="277349" />
                        <vc:DataPoint AxisXLabel="6/1/08" YValue="351139" />
                        <vc:DataPoint AxisXLabel="7/1/08" YValue="345254" />
                        <vc:DataPoint AxisXLabel="9/1/08" YValue="318845" />
                        <vc:DataPoint AxisXLabel="10/1/08" YValue="274316" />
                        <vc:DataPoint AxisXLabel="11/1/08" YValue="297349" />
                        <vc:DataPoint AxisXLabel="12/1/08" YValue="237349" />
                        <vc:DataPoint AxisXLabel="1/1/08" YValue="353139" />
                        <vc:DataPoint AxisXLabel="2/1/08" YValue="385989" />
 
                        <vc:DataPoint AxisXLabel="3/1/08" YValue="435989" />
                    </vc:DataSeries.DataPoints>
                </vc:DataSeries>
            </vc:Chart.Series>
        </vc:Chart>

You will notice I also added a bit of sample data.  In my actual XAML form things are setup as shown below.

<Window x:Class="ClientApp.PrototypeReportView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="PrototypeReportView" Height="500" Width="500">
    <Grid Background="Black">
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
    </Grid>
</Window>

Under the </Grid> and above the </Window> tags I added the chart XAML above.  Now simply run the application and view the chart.  Mine shows up as shown below.

The data I plugged in is some sample data from the Webtrends DX Web Services.  In the near future I am intending to hustle up some connections to actual Webtrends DX Web Services, so I can show how to wire up to some live, changing, or even real time data.

Shout it kick it on DotNetKicks.com
Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Posted by: Adron
Posted on: 12/8/2009 at 5:10 PM
Tags: , , ,
Categories: How-To, Samples, and Such | Web Analytics | WebTrends
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (5) | Post RSSRSS comment feed