Quantcast
Channel: Telerik Blogs | .NET
Viewing all 1954 articles
Browse latest View live

Building Fiddler Importers

$
0
0

Learn how to build your own Fiddler importers with this simple guide.

This is a guest post from Eric Lawrence, written in collaboration with the Fiddler team. Would you like to write about Fiddler for our blog? Let us know in the comments below.

When reproducing a bug on a website or web service, traffic captures are invaluable because they allow developers and testers to easily see exactly what’s going on at the network level, even without having access to the reproduction environment. Over the years, Fiddler’s Session Archive Zip (SAZ) file format has become the gold standard for such captures because SAZ files are easily captured (with Fiddler, Fiddler Everywhere, FiddlerCap, or a Fiddlercore-based tool) and are easily reviewed with the powerful Fiddler desktop client.

However, in some cases, you may wish to debug network traffic that was originally captured using another tool and exported in a format like a Wireshark PCAP or the browser-standard HTTP Archive Format (HAR). Fiddler already includes importers for those formats, but what if you want to support a different format that Fiddler doesn’t yet support?

Fortunately, Fiddler is extremely extensible, and this extends to the import/export system. We’ve previously published an example exporter, and today I’d like to talk about how you can build an importer.

I’m now an engineer on the Microsoft Edge browser team, and our preview builds are now being tested by users around the world. When those users encounter problems, sometimes the best path for debugging starts with capturing a network traffic log. For some of our more technical users, that might involve collecting a SAZ file using one of the existing Fiddler-* products. But for other users (especially our upcoming MacOS users), collecting a SAZ file involves more overhead. In obscure cases, collecting a SAZ file might cause a repro to disappear.

Fortunately, the new Microsoft Edge browser is built atop the Chromium open-source browser engine, and Chromium includes a built-in network logging feature. To collect a network log in Edge, simply navigate a tab to edge://net-export (in Google Chrome, you’d visit chrome://net-export instead).

Configure the options using the radio buttons and click Start Logging to Disk. Open a new tab and reproduce the problem. After you’ve completed the repro, click Stop Logging. At the end, you’ll have a NetLog .json file containing all of the network events. The output JSON file can be viewed using a web-based viewer:

However, in many cases, it would be more desirable to view the file using Fiddler. Unlike the web based viewer (which tends to show content as a base64-encoded string of goo), Fiddler includes built-in formatters for common web formats (e.g. images, JSON, etc), and it makes it easier to export response bodies as files, resend captured requests using the Composer, and replay captured responses using the AutoResponder.

Fiddler does not include a NetLog importer by default, so let’s build one.

First, we start by looking at the Chromium documentation for the relatively straightforward file format. NetLog files are JSON-serialized streams of network events. The low-level events (tracking DNS lookups, TCP/IP connections, HTTPS certificate verifications, etc) are associated to a request identifier, which represents one or more network requests (what Fiddler calls a “Web Session”). So, the task of our importer is to:

  1. Parse the JSON file into a list of events
  2. Bucket the events by the request identifiers
  3. Generate one or more Fiddler Web Sessions from each bucket

The C# sourcecode for the FiddlerImportNetlog extension is available on Github. Beyond all of the typical project files, the extension itself consists of just two files, Importer.cs, FiddlerInterface.cs, and Properties\AssemblyInfo.cs.

The AssemblyInfo.cs contains just one line of interest:

[assembly: Fiddler.RequiredVersion("4.6.0.0")]

Fiddler requires this attribute to load the assembly as an extension; it specifies the minimal version of Fiddler you’ve tested the extension to run in.

The FiddlerInterface.cs file contains a simple class which implements the ISessionImporter interface. The ProfferFormat attribute on the class specifies the format type and a descriptive string to show in the import dialog:

The importer interface exposes a single method, ImportSessions, which accepts a string specifying the selected format, a dictionary of options, and an optional event handler to call back with import progress events. The function returns an array of Sessions created from the imported data.

The bulk of the extension’s logic is found in Importer.cs. The caller provides a StreamReader from which the imported file’s text is read and then parsed using the JSON.JsonDecode method made available by the using Fiddler.WebFormats statement at the top of the file. WebFormats.JSON is a fast, simple parser that reads the JSON into Hashtables (for JS objects), ArrayLists (for JS arrays), and primitive types (booleans, doubles, strings, etc).

After parsing, the importer looks up the mappings from named event types (e.g. URL_REQUEST_START_JOB) to the integer identifiers recorded inside the event entries, then parses the list of event entries, bucketizing those with a source of URL_REQUEST by the request id. Then, the ParseSessionsFromBucket method loops over each URL_REQUEST’s events to collect the data (e.g. request headers, response headers, response bodies) needed to generate a Fiddler Web Session. Two notable details:

  1. The NetLog format may have multiple request/response pairs in a single URL_REQUEST (e.g. if the request resulted in a redirect or an automatic authentication challenge/response)
  2. The NetLog format does not presently store (anywhere) the request body content for POST requests. In contrast, response body bytes may or may not be present based on the options chosen by the user when starting the logging process

After generating the list of extracted Web Sessions, the importer generates a few “mock” Sessions that allow the user to peruse the raw data captured in the file (e.g. the browser configuration, list of enabled extensions, etc).

After an hour of quick-and-dirty coding, Fiddler can now import NetLog json files:

If you’re just interested in using this importer without building it yourself, you can install it from my website. If you find any bugs, please file them!

Hopefully, you’ve found this to be a useful introduction to how easy it is to build importers to get your data into Fiddler!


How to Achieve Chrome-like Tabs with Tabbed Form in WinForms applications

$
0
0

This post will introduce you to the Tabbed Form control and its features, and we'll see how to achieve tabbed navigation in your WinForms application.

We introduced the Telerik UI for WinForms RadTabbedForm in the R1 2019 version of the controls. I hope that by now you have played with it and seen how handy it can be in so many scenarios. In this blog post I will try to explain some of the scenarios the control handles and later go over the features in more depth.

tabbed-form-01

Where to Use Tabbed Form?

The idea to organize the different views of an application in separate tabs is not new. The Microsoft TabControl and our own RadPageView have been around for quite some time. Although powerful, these controls serve a more limited purpose. Imagine, that you want to implement a tabbed UI which will serve as a top-level container of the entire application. The page view and MS tab control are not suitable for this as they are bound to the form they were added to and the pages or tabs cannot be dragged and dropped. Actually, a dock control can better serve you, yet if you want to achieve an end-user experience like what people are seeing in the modern browsers, it is still not good enough.

The RadTabbedForm is specifically built to handle this scenario. The application content can be organized and separated in different tabs where each tab is responsible for a different part of the application. The tabs are located inside the form's title bar just like in browsers (Chrome, Edge etc.) and they can be reordered or moved away to a separate window. This is extremely useful in big applications visualizing data. Instead of switching from one tab to another, the end user could simply drag the tab out thus creating a new form. The tabs would then be in two separate windows and the user could easily view both contents simultaneously. RadTabbedForm offers great flexibility and freedom which will be appreciated by the people using your application.

The screenshot below shows two tabs with the second tab being detached in a separate form. The first tab displays a RadPivotGrid and the second one shows a breakdown of the grouped and aggregated data behind the selected cell in the pivot from the first tab.

tabbed-form-011

Architecture and Features

The RadTabbedForm represents a form host of the RadTabbedFormControl. The form control is responsible for creating and manipulating the tabs in the title bar, the panels associated with each tab holding their content and the drag-drop service. Basically, most of the functionality and API is defined inside the RadTabbedFormControl, which is exposed by the form's TabbedFormControl property. The control is packed with many features and its look can be completely customized by simply setting a couple of properties. The form is built on top of TPF consisting of many light-weight visual elements. The Structure article in the documentation provides information on the more important building blocks of the control.

Full Design Time support

Tabs can be added in the designer of Visual Studio. Each tab will create a panel where all the other controls can be added.

RadTabbedForm with the Fluent Theme in the Visual Studio Designer

tabbed-form-02

Title Bar Support

It was really challenging to implement all the features inside the form's non-client area. I am happy to say that we managed to achieve everything which was planned.

  • Settings: The title bar’s height is not fixed, and it can be adjusted via the CaptionHeight property. The tabs height and the space between them is also adjustable. We have decided to leave no space between the tabs, however, if your end users would need such you can increase the tab spacing. For example, with the following settings you can increase the height of the entire title bar and have the tabs displayed under the top-part where the form`s icon and system buttons are located. This way you will have a bigger part of the non-client area empty which will allow the users to move the form easily.

    this.ShowIcon = true;
    this.TabbedFormControl.ShowText = true;
    this.TabbedFormControl.CaptionHeight = 65;
    this.TabbedFormControl.TabHeight = 32;
    this.TabbedFormControl.TabWidth = 180;
    this.TabbedFormControl.TabSpacing = 12;
Default and Customized Tabbed Forms

tabbed-form-03

  • Standard Windows Title Bar Style: What does it mean? Basically, it means that we can paint the tabs inside the default Windows title bar as it is painted by the operating system. This will vary from one Windows version to another and it will also depend on the chosen Windows theme. This behavior is controlled by the AllowAero property of the form. Setting the property to false would force our themes and the control will adjust the title bar to match the theme of the tabbed control. In some situations, it might be necessary to match the standard Windows look so the AllowAero property has you covered:

    this.AllowAero = true;

Standard Windows 10 Title Bar Style

tabbed-form-04

Drag and Drop

The tabs can be reordered inside the title bar. It is also possible to drag them out to create a separate form. The tab content including all the added controls will be moved to the new form. This operation can be repeated numerous times over and the tab be moved from one form to another.

tabbed-form-drag-drop

Quick Actions

Various elements like buttons, check boxes, drop-down buttons etc. can be added before and/or after the tabs.

this.TabbedFormControl.LeftItems.Add(newRadButtonElement { Text = "button1"}); //adds items before the tabs
this.TabbedFormControl.RightItems.Add(newRadButtonElement { Text = "button2"}); //adds items after the tabs

These elements can be also added in the Visual Studio designer.

tabbed-form-05

The LeftItems and RightItems collections are also exposed in the property grid of the designer and the elements can be edited in the collection editor.

tabbed-form-06

Navigation

The tabbed control also has a built-in navigation. The navigation buttons will appear automatically, whenever the tabs cannot fit entirely in the available width. The tabs always have an equal width and it can be controlled with the TabWidth and MinimumTabWidth properties. The layout is smart enough and if the tabs count is increased to a point that they cannot fit in the title bar with their specified width, the widths of all tabs will be decreased equally. The layout will decrease the widths of the tabs until it reaches the specified MinimumTabWidth value. At that moment the navigation buttons will become visible.

tabbed-form-navigation

Pinned Items

Tabs can be pinned to the left or right side of the title bar. When unpinned, the tab will return to its last position.

this.TabbedFormControl.Tabs[0].Item.IsPinned = true;

tabbed-form-07

Context Menu

The tabbed control also has a built-in context menu which is fully localizable.  

tabbed-form-08

The items displayed in the menu can be customized in the RadTabbeFormControl.ContextMenuOpening event.

privatevoidTabbedFormControl_ContextMenuOpening(objectsender, RadTabbedFormControlItemConextMenuOpeningEventArgs e)
{
    if(e.TabItem.Text == "Tab 1")
    {
        //remove first item
        e.ContextMenu.Items[0].Visibility = ElementVisibility.Collapsed;
    }
    elseif(e.TabItem.Text == "Tab 2")
    {
        //disable the context menu
        e.Cancel = true;
    }
}

Getting Started

There are two ways to add a RadTabbedForm to your Visual Studio project:

  • VSX extensions: Assuming that you have our Visual Studio extensions installed, you can create a new tabbed form by simply adding a new item to the project.

tabbed-form-09

  • RadFormConverter: Simply drag and drop the component from the Visual Studio tool box and convert the current form to a RadTabbedForm.

Once you have the form added to the project you can start building the UI. Tabs can be added via the RadTabbedFormControl's smart tag. The smart tag also exposes the most important properties of the control. You can also check our Demo application and the two RadTabbedForm examples. Please also don't miss the documentation as it provides detailed information on the features and API of the control.

Try It Out and Share Your Feedback

We'd love to hear what your thoughts are on the new control. Please leave a comment below or write in the forums. If you have an idea for the next great feature you can also submit it on our feedback portal.

You can learn more about the Telerik UI for WinForms suite via the product page. It comes with a 30-day free trial, giving you some time to explore the toolkit and consider how it can help you with your current or upcoming WinForms development.

Create Accessible PDF Documents with Telerik Reporting

$
0
0

Our latest addition to the accessibility story is enabling the PDF rendering extension to produce PDF files that comply with the PDF/UA standard. 

Whether we are writing code, authoring an article or composing a poem, we usually want to get our message delivered to as many people as possible. Sharing our work with others is getting much easier with the advantages that modern technology gives us. This task gets even more important when the shared information represents business data that needs to be accessed by a broader audience.  

A key factor here is to choose a suitable medium, and Adobe’s PDF file is arguably the best way to spread the message. PDF stands for Portable Document Format and indeed it is a well-established standard for creating and distributing documents, which can be read on virtually any current platform and device. But the PDF standard has one more very important feature – it can produce documents in a way that allows users with disabilities to be able to perceive the shared information. This feature is called accessibility and is defined by the PDF/UA standard which is aimed at production companies of software and assistive technologies. 

Accessible PDF Documents

We on the Telerik Reporting team introduced accessibility support in R3 2017 and have since continued evolving further in this direction. Our latest addition to the accessibility story is enabling the PDF rendering extension to produce PDF files that comply with the PDF/UA standard. The most important characteristics of these files are listed below:
  • Tagged contents - all textual items in the report will have a corresponding accessibility entry in the PDF structure. This entry contains the text recognized by the screen readers and other assistive technologies. The rules to generate the text in tagged contents are the same used to generate the metadata in rendered report contents and can be checked here
  • Description for non-textual items - the PictureBox, Graph and Map items should provide meaningful accessible descriptions as well. This description is persisted in a tagged element with configured actual and alternate text. Other graphical primitives like borders will be treated as non-informational elements and will be added in the PDF document structure as artifacts. 
  • Annotations - all the links in the document have a respective link annotation object in the PDF structure. The purpose of the link annotation objects is to provide additional information about the currently selected navigational link. 
  • Document Title - the title is obtained from the PDF device information settings that can be set via code or through the configuration file. When unavailable, the DocumentName property of the report will be used instead. 
  • Document Natural Language– like the document’s title, the document language should be set in the PDF device information settings. If unavailable, the value of the Culture.Name property of the report will be used instead. 

Configuration 

The setting that determines whether the reporting engine would add the accessibility information to the PDF document is named enableAccessiblity and is passed through the PDF device information settings. The settings can be also controlled from the report viewer’s EnableAccessibility property, providing a consistent behavior between viewed content and exported documents. Since the report viewer setting has a broader scope, it has lower priority than the settings explicitly set in device information object. The accessibility feature can also be enabled in code, for example, when the PDF file is produced from the ReportProcessor class:

var rs = newTypeReportSource() { TypeName = typeof(Dashboard).AssemblyQualifiedName };
var deviceInfo = newHashtable()
{
    { "EnableAccessibility", true}
};
var result = newReportProcessor().RenderReport("PDF", rs, deviceInfo);
File.WriteAllBytes("AccessibleDashboard.pdf", result.DocumentBytes);

Results Assessment

The most complete document that describes the checks that a PDF file needs to pass to satisfy PDF/UA standard, is the Matterhorn Protocol. It specifies which of the failure conditions can be tested with dedicated software and which need to be examined manually. Based on this protocol, many tools can evaluate the produced PDF document and determine if it complies to the accessibility standards established with PDF/UA.

For example, Adobe Acrobat provides a thorough test that traverses the PDF structure and its metadata and outputs a detailed report as shown below:

PDF accessibility check on Adobe Acrobat

Another comprehensive and free testing tool is PAC - PDF Accessibility Checker. PAC is built in accordance with the Matterhorn protocol and evaluates all the failure conditions that can be tested with a software product. It also includes a screen reader preview that helps to determine how the document will be interpreted by screen-reading applications like NVDA and JAWS, utilized by the visually impaired users. The report that PAC tool displays when checking a PDF/UA compliant file looks like this:

PDF Accessibility Check by PAC

Want to Learn More?

If you are new to our tools or have only tried some, make sure you download the trial and take them for a spin. You can either download just the Reporting and Report Server tools, or download a trial of our entire set of .NET and JavaScript tools with the DevCraft bundle.

We're eager to hear what you think, so please don't forget to share your feedback and help us make Telerik Reporting even better.

WPF/ Silverlight: RadGauge Layout Composition

$
0
0

Today I would like to highlight one of the newest controls added to the WPF / Silverlight control suites in November – the RadGauge control.

RadGauge combines its rich assortment of radial, linear and numeric gauge types with very flexible layout composition abilities thus allowing you to attain a new level of data visualization quickly and easily.

Let us discuss the basics of the layout composition and how it is implemented in the gauge control.

There are three levels of controls that participate in the layout:

  • RadGauge
  • LinearGauge / RadialGauge
  • LinearScale / RadialScale / NumericScale

 

RadGauge is the top level class but as far as the control is concerned this is simply a container that holds the rest of the building blocks together. RadGauge can contain any mixture of layout controls (grids, panels), LinearGauge (RadialGauge) containers, and even LinearScale / RadialScale / NumericScale instances.

LinearGauge (RadialGauge) is a container that normally stores the set of linear (respectively radial) and numeric scales. One of the major goals of this container control is the ability to create common appearance for your linear (radial) gauges. The default template looks like this:

<ControlTemplate>
   
<Border Background="{TemplateBinding Background}"                            
            BorderBrush
="{TemplateBinding BorderBrush}"
            BorderThickness
="{TemplateBinding BorderThickness}">
       
<Grid>
           
<ContentControl Template="{StaticResource RadialGaugeBackground}"/>
            <
ItemsPresenter />
            <
ContentControl Template="{StaticResource RadialGaugeForeground}"/>
        </
Grid>
   
</Border>
</ControlTemplate>

In this way you can define the background and the foreground content for all scales shown in one gauge and achieve artistic look for your gauges with different effects (e.g. place the radial image as background and add some “glassy” gradient as foreground). Note that it is not compulsory to use the LinearGauge / RadialGauge container e.g. if you prefer plain range display, you can place LinearScale / RadialScale / NumericScale instances directly in the RadGauge control content.

LinearScale / RadialScale / NumericScale instances provide all of the essential gauge logic. These controls host other elements (tick marks, labels and indicators) and provide functionality to manage appearance and positioning of these elements.

 

OK, let us see some examples that visualize the concepts described so far:

The most common approach to display radial gauge would be to use the RadGauge –> RadialGauge –> RadialScale hierarchy like this:

<telerik:RadGauge Grid.Row="1" Name="RadGauge1">
   
<telerik:RadialGauge Name="RadialGauge1" Width="300" Height="300">
       
<telerik:RadialScale Name="radialScale" Min="0" Max="8000" Center="0.5,0.5" 
            Radius
="0.75" StartWidth="0.15" StartAngle="120" SweepAngle="300" BorderBrush="Transparent" 
            IsLabelRotated
="True" MajorTicks="8" MiddleTicks="1" MinorTicks="6">
           
<telerik:RadialScale.MajorTick>
               
<telerik:TickProperties Length="0.15" />
            </
telerik:RadialScale.MajorTick>
           
<telerik:RadialScale.MinorTick>
               
<telerik:TickProperties Length="0.1" TickWidth="0.1" Location="OverInside" />
            </
telerik:RadialScale.MinorTick>
           
<telerik:RadialScale.Label>
               
<telerik:LabelProperties />
            </
telerik:RadialScale.Label>
           
<telerik:RadialScale.Indicators>
               
<telerik:Needle Name="marker" IsAnimated="True" SnapType="ToGrid">
               
</telerik:Needle>
           
</telerik:RadialScale.Indicators>
       
</telerik:RadialScale>
   
</telerik:RadialGauge>
</telerik:RadGauge>
 
 radial1
 
If you would like to achieve more plain display (no orange background ellipse and “glassy” foreground look), you can show only the range scale by omitting the RadialGauge container like this:
 
<telerik:RadGauge Grid.Row="1" Name="RadGauge1">
   
<telerik:RadialScale Width="300" Height="300" Name="radialScale" Min="0" Max="8000" Center="0.5,0.5" 
        Radius
="0.75" StartWidth="0.15" StartAngle="120" SweepAngle="300" BorderBrush="Transparent" 
        IsLabelRotated
="True" MajorTicks="8" MiddleTicks="1" MinorTicks="6">
       
<telerik:RadialScale.MajorTick>
           
<telerik:TickProperties Length="0.15" />
        </
telerik:RadialScale.MajorTick>
       
<telerik:RadialScale.MinorTick>
           
<telerik:TickProperties Length="0.1" TickWidth="0.1" Location="OverInside" />
        </
telerik:RadialScale.MinorTick>
       
<telerik:RadialScale.Label>
           
<telerik:LabelProperties />
        </
telerik:RadialScale.Label>
       
<telerik:RadialScale.Indicators>
           
<telerik:Needle Name="marker" IsAnimated="True" SnapType="ToGrid">
           
</telerik:Needle>
       
</telerik:RadialScale.Indicators>
   
</telerik:RadialScale>
</telerik:RadGauge>

radial2

 

Moreover, you can mix various gauge visuals and layout controls like this:

 - Grid

       - LinearGauge

              - LinearScale

       - StackPanel

              - RadialGauge

                     - RadialScale

              - RadialScale

    <telerik:RadGauge Grid.Row="1" Name="RadGauge1">
       
    <Grid Width="520" Height="400">
           
    <Grid.ColumnDefinitions>
               
    <ColumnDefinition Width="Auto" />
                <
    ColumnDefinition Width="Auto" />
            </
    Grid.ColumnDefinitions>
           
    <telerik:LinearGauge Width="120" Height="370" Margin="15">
               
    <telerik:LinearScale Min="0" Max="100" MajorTicks="10" MiddleTicks="1" MinorTicks="5">
                   
    <telerik:LinearScale.MajorTick>
                       
    <telerik:TickProperties Length="0.1" TickWidth="0.1" Location="OverCenter">
                       
    </telerik:TickProperties>
                   
    </telerik:LinearScale.MajorTick>
                   
    <telerik:LinearScale.MiddleTick>
                       
    <telerik:TickProperties Length="0.025" TickWidth="0.5" Location="OverCenter"/>
                    </
    telerik:LinearScale.MiddleTick>
                   
    <telerik:LinearScale.MinorTick>
                       
    <telerik:TickProperties Length="0.02" TickWidth="0.3" Location="OverCenter"/>
                    </
    telerik:LinearScale.MinorTick>
                   
    <telerik:LinearScale.Label>
                       
    <telerik:LabelProperties />
                    </
    telerik:LinearScale.Label>
               
    </telerik:LinearScale>
           
    </telerik:LinearGauge>
           
    <StackPanel Orientation="Vertical" Grid.Column="1">
               
    <telerik:RadialGauge Name="RadialGauge1" Width="200" Height="200">
                   
    <telerik:RadialScale Name="radialScale" Min="0" Max="8000" Center="0.5,0.5" 
                        Radius
    ="0.75" StartWidth="0.15" StartAngle="120" SweepAngle="300" BorderBrush="Transparent" 
                        IsLabelRotated
    ="True" MajorTicks="8" MiddleTicks="1" MinorTicks="6">
                       
    <telerik:RadialScale.MajorTick>
                           
    <telerik:TickProperties Length="0.15" />
                        </
    telerik:RadialScale.MajorTick>
                       
    <telerik:RadialScale.MinorTick>
                           
    <telerik:TickProperties Length="0.1" TickWidth="0.1" Location="OverInside" />
                        </
    telerik:RadialScale.MinorTick>
                       
    <telerik:RadialScale.Label>
                           
    <telerik:LabelProperties />
                        </
    telerik:RadialScale.Label>
                       
    <telerik:RadialScale.Indicators>
                           
    <telerik:Needle Name="marker" IsAnimated="True" SnapType="ToGrid">
                           
    </telerik:Needle>
                       
    </telerik:RadialScale.Indicators>
                   
    </telerik:RadialScale>
               
    </telerik:RadialGauge>
               
    <telerik:RadialScale Width="200" Height="200" Min="0" Max="8000" Center="0.5,0.5" 
                    Radius
    ="0.75" StartWidth="0.15" StartAngle="120" SweepAngle="300" BorderBrush="Transparent" 
                    IsLabelRotated
    ="True" MajorTicks="8" MiddleTicks="1" MinorTicks="6">
                   
    <telerik:RadialScale.MajorTick>
                       
    <telerik:TickProperties Length="0.15" />
                    </
    telerik:RadialScale.MajorTick>
                   
    <telerik:RadialScale.MinorTick>
                       
    <telerik:TickProperties Length="0.1" TickWidth="0.1" Location="OverInside" />
                    </
    telerik:RadialScale.MinorTick>
                   
    <telerik:RadialScale.Label>
                       
    <telerik:LabelProperties />
                    </
    telerik:RadialScale.Label>
                   
    <telerik:RadialScale.Indicators>
                       
    <telerik:Needle Name="marker2" IsAnimated="True" SnapType="ToGrid">
                       
    </telerik:Needle>
                   
    </telerik:RadialScale.Indicators>
               
    </telerik:RadialScale>
           
    </StackPanel>
       
    </Grid>
    </telerik:RadGauge>

    radial3

     

    Hope this overview helps.

    RadGrid for ASP.NET AJAX Performance Optimization

    Introducing Task-It. A real-world application using RadControls for Silverlight 4

    $
    0
    0

    Task-It Series

    This post is part of a series of blog posts and videos about the Task-It (task management) application that I have been building with Silverlight 4 and Telerik's RadControls for Silverlight 4. For a full index of these resources, please go here. One of the posts listed in the index provides a full source download for the application.

    Introduction

    This is the first in a series of blog posts based around an application called Task-It that I have developed in Silverlight 4. Task-It is real-world application designed for people that need a simple way to manage the numerous tasks that we all strive to accomplish on a daily basis.

    Task-It Tasks Page
    Figure 1: Task-It Tasks page

    Task-It Dashboard Page
    Figure 2: Task-It Dashboard page

    I have developed this application for several reasons:

    • There are many task management applications out there, and I have used quite a few of them, but I haven’t found one that really ‘grabbed’ me. Many of these applications had their strong points,but some were overly complex, some lacked key features, some cost too much money, and so forth. I thought it would be nice to identify the best parts of each, and take my stab at building my own.
    • During my evaluation of task management applications, I have not yet found one built in Silverlight.
    • Building this application in Silverlight 4 is good way to showcase some best practices in the areas of technology and user experience design, leverage the latest that Microsoft has to offer, and leverage the richness and power of Telerik RadControls for Silverlight.
    • To provide guidance to other developers that are interested in Silverlight and Telerik’s Silverlight control set, as well as those that are already using both. Having said this, Task-It is far from perfect. It is a version 1 release developed by a single developer. It will continue to evolve over the coming months, as will the techniques I use to make it tick.

    Why Silverlight?

    Whether you are new to Silverlight or you have been dabbling with through each of its major releases, you are probably either very intrigued with the technology, or you are convinced (as I am) that this is the future of web application development. However, it is almost impossible to not be intimidated by the fact that this technology is moving very quickly, and that there is a boatload of information out there that surrounds it. A simple Google search on ‘Silverlight’ is proof of that. Just keep in mind that this is not a bad thing. If there was very little information, you’d be wise to choose another technology…right?

    My first experience with Silverlight was at Tech Ed 2007. At that time it wasn’t much more than a media player, but already I could ‘see the light’. I knew that Microsoft had plans to grow this into a rich platform for the development of web applications…and I was hooked!

    Information Overload

    So, if you are going to dive deeper into Silverlight (or even if you already have), you’ve undoubtedly had numerous questions around what the best way is to implement a LOB (line-of-business) application? You can spend weeks and months plowing through hundreds of blog posts, videos, webcasts, etc. trying to figure out the answers. What you will find is that there are a myriad of different opinions and approaches to various problems that you want to solve (and a lot of information that is already very out-of-date). You’ll also come across mention of numerous frameworks, open source projects, and things like MVVM, Prism, MEF, WCF RIA Services, DI (Dependency Injection), IOC (Inversion of Control), TDD (test-driven development) and so on. Wow, this is a lot of stuff to grasp, and there is more and more every day! Is this a mistake? Should you turn back to whatever technology you are currently using and hope that this technology fails? Yikes, but what if this technology takes off and you’re caught behind the times? As we all know well, keeping up is one of the keys to staying employed in this industry.

    I’d be willing to bet that just about every person has experienced these thoughts…I know I certainly have, and to be honest, occasionally still do. But as I mentioned before, I truly believe that Silverlight is the future of web application development, and as my level of comfort with these frameworks and terms has increased, my level of excitement continues to grow. I know that I am riding a very exciting wave into the future…and it’s a very good thing.

    The Road to Silverlight

    Just to give you a little background, I have been developing web-based applications for 13+ years in technologies such as ColdFusion, JSP, Java Swing, ASP, ASP.NET, and now Silverlight. Over these years I have worked a lot of hours, and to be honest, wasted a lot of time battling things that I felt should’ve been a lot easier to accomplish than they were. Along the way the development team I was a part of often had a product release coming up that was running behind schedule, and management was asking the developers to put in ‘that extra effort to get us over the finish line’. If you haven’t been there, you probably just graduated last week.

    So, does anyone really enjoy being in that position? I can’t say that I have, and over those years what usually stood in my way was the technology I was working with. Things that seemed like they should be easy just weren’t. I’d be in a situation where the web application I was producing seemed like it was really coming along well, when all of a sudden the next version of IE came along, or the next version of Firefox, or Google came out with their own browser…and suddenly everything went south. The app that looked great now looked horrible, and it was back to working weekends. More time was spent fixing bugs than actually developing new features. Been there, done that?

    Only two languages…really?

    OK, so let’s say that you can at least relate to part of what I’ve said so far. Let’s take a look at how many languages you’ve had to learn to build your web applications. A quick look at job postings on sites like Monster or Dice will show that employers building web-based application generally require some level of proficiency with at least HTML, CSS, JavaScript and either C#, VB.NET or Java. If you’re skills are pretty strong in these languages you’re probably in ok shape even in a down economy, but what if someone came to you and said this:

    “How would you feel if you could develop rich, compelling web applications with cool user interaction like you see on those iPhone commercials, and you only have to know 2 development languages? Oh, and what if you could build these apps without having to spend months making them look the same in IE8 on Windows, IE7, IE6, Firefox 3 on Mac, Google Chrome, etc., etc.?”

    Intrigued? Yeah, you should be. This is the way life should be. You build a cool application, your boss and your customers are happy, and you can actually go home and spend time with your family at night. Almost sounds too good to be true doesn’t it?

    With Silverlight, you can develop an application in 2 languages. XAML is the language used for layout (this is the Silverlight equivalent of HTML). When it comes to the other language you have a choice, but the one most commonly chosen is either C# or VB.NET. You can certainly introduce more languages to your application, but in many cases 2 languages will do just fine. Of course, most applications will require database access and will require skills surrounding that layer (SQL, stored procedures, etc.), but that may or may not be part of your job as a developer.

    Can it really be that easy?

    Well, truthfully, not entirely. Nothing is perfect, and every technology has its shortcomings and challenges. However, Silverlight is not a version 1 product. Version 4 is fast approaching…and love ‘em or hate ‘em, nobody has more experience with putting this stuff together than Microsoft. I know, some folks don’t trust them, but this is a new generation, and Silverlight is not a Window-only technology. It produces applications that can run on multiple platforms and browsers. We’re not just talking IE on Windows here .The times, they are a changing.

    Silverlight is not perfect, and as with any technology there are some things that you wish could be a little easier to pull off than they are, but nothing in this world is perfect, and Microsoft is moving at breakneck speed with this technology. Things are getting better every day, and we as developers can truly reap the benefits. Good software will never write itself, if it did you and I would be looking for a new line of work, but I honestly believe that with each day that approaches the time spent on developing applications will be focused more around producing a rich, compelling user experiences than battling cross-browser CSS issues and bug fixes.

    I’m not just an employee…

    By the way, I became an employee of Telerik in early January of 2010, but prior to that I had been a Telerik customer for more than 4 years. I have used Telerik controls in ASP.NET, ASP.NET AJAX, Silverlight and WPF projects for 4 different employers over that period. Along the way I evaluated and utilized several 3rd party .NET control sets and chose Telerik because of their quality, support, and features.  So as I continue to blog about the use of Telerik controls in the products I am developing it is not simply because the company is signing my paycheck, it is because I honestly believe that incorporating Telerik controls allow me to produce applications that are better and richer in a shorter period of time.

    Keep an eye out for MEF

    One of the frameworks that I did choose to leverage in the development of Task-It is MEF (Managed Extensibility Framework). I’ll be posting some blogs later this week about how I used it for dynamic XAP loading and maintaining state in Task-It, so please keep an eye out for those posts.

     

    Silverlight Recruiting Application #9 - Adding RadUpload (Part 2)

    $
    0
    0

    Yesterday we saw all the plumbing involved to lay a groundwork for RadUpload being used to add files to applicants. Today we actually dive into the code for getting RadUpload working in the MVVM application.

    The first step in this is deciding where to add the ability to upload files. Doing this within the main Applicants grid is nice (since we're already using the RowDetails presenter), but that'll clutter up the UI there as I want to switch that into a quick and easy overview of each applicant. So instead we're modifying the AddEditApplicantView to make it tab-based, providing one tab for the regular information and the other for handling the file uploads (and project rating, since we do have a RadRating control now!). I'll spare you the markup, but here is the new UI:

    New UI for Add/Edit Applicant View

    Do you see the RadUpload instances? Neither do I, that's because they have Visibility set to Collapsed and we're handling all actions through the RadUploadDropPanel and attached behaviors on RadUpload. Since we now utilize DropTarget support with RadUpload, we don't even need to see the control anymore to take advantage of the fast upload capabilities it gives us. To get into the code a little, here is the XAML markup for the first instance of RadUploadDropPanel, RadUpload, and the corresponding HyperlinkButton:

     

    <telerik:RadUploadDropPanelx:Name="xResumeDropPanel"
                                Grid.Row="1"
                                Grid.Column="1"
                                AllowDrop="True"
                                DragOver="xResumeDropPanel_DragOver"
                                DragLeave="xResumeDropPanel_DragLeave"
                                Drop="xResumeDropPanel_Drop"
                                RadUpload="{Binding ElementName=xResumeRadUpload}">
        <Borderx:Name="xResumeUploadBorder"
                Margin="5"
                Background="LightBlue"
                Height="30">
            <TextBlockHorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        Text="Resume"/>
        </Border>
    </telerik:RadUploadDropPanel>
    <telerik:RadUploadx:Name="xResumeRadUpload"
                        AllowDrop="True"
                        IsAutomaticUpload="True"
                        UploadServiceUrl="/HRUpload.ashx"
                        OverwriteExistingFiles="True"
                        TargetPhysicalFolder="{Binding UploadTargetFolder}"
                        command:UploadStartedEventClass.Command="{Binding UploadStartedCommand}"
                        command:UploadFinishedEventClass.Command="{Binding UploadFinishedCommand}"
                        command:FileUploadedEventClass.Command="{Binding FileUploadFinishedCommand}"
                        Grid.Row="1"
                        Grid.Column="3"
                        Visibility="Collapsed"
                        d:DesignHeight="10"
                        d:DesignWidth="10"/>
    <HyperlinkButtonx:Name="xResumeUploadTextBlock"
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        Content="{Binding ResumeUploadStatus}"
                        Foreground="{Binding ResumeUploadStatus, Converter={StaticResource StatusToColorConverter}}"
                        NavigateUri="{Binding ActiveApplicant.Resume}"
                        TargetName="_blank"
                        Grid.Row="1"
                        Grid.Column="2"/>

     

    And we also get a little bit of code-behind:

    // I'm not a bad MVVM programmer, but creating behaviors in order to 
    //   modify the drag-over color for the RadUploadPanel content is 
    //   overkill - this is strictly a view-related issue and therefore
    //   it is okay to have strictly view-related code in the code-behind. :)
    privatevoidxResumeDropPanel_DragOver(objectsender, DragEventArgs e)
    {
        ((sender asRadUploadDropPanel).Content asBorder).Background = newSolidColorBrush(Colors.Orange);
    }
    privatevoidxResumeDropPanel_DragLeave(objectsender, DragEventArgs e)
    {
        ((sender asRadUploadDropPanel).Content asBorder).Background = newSolidColorBrush(Color.FromArgb(255, 96, 194, 255));
    }
    privatevoidxResumeDropPanel_Drop(objectsender, DragEventArgs e)
    {
        ((sender asRadUploadDropPanel).Content asBorder).Background = newSolidColorBrush(Color.FromArgb(255, 96, 194, 255));
    }

     

    For those MVVM purists, yes, there is code in my code-behind, but I've got a very specific reason for that (explained in the comments, but I'll touch on it again). The DragOver, DragLeave, and Drop events are only effecting something in the view and have nothing to do with the overall data model for the application. So for each I could have gone the route of creating an attached behavior, setting the colors in the viewmodel to bind to the drop panels, and adding more code to my viewmodel to ensure this all works without a hitch, but why? This works, it only impacts the view, and is a more streamlined and less time-consuming approach than all that. 

    Back on track, in order of appearance we see our RadUploadDropPanel that is bound to the xResumeRadUpload (therefore any files dropped on the drop panel get added to RadUpload), with a simple border and textblock being used to provide a UI that updates based on whether the user is dragging a file over it or not.

    Next is RadUpload, where all the magic is going to happen:

    • IsAutomaticUpload is true so that once a file is dropped on the respective upload panel, RadUpload runs with it and attached behaviors cover the rest of our interaction
    • UploadServiceUrl points to a standard RadUpload upload handler in the .Web project (instructions here on the basic setup I used)
    • OverwriteExistingFiles is true because I trust my HR people to handle their uploads properly
    • TargetPhysicalFolder is bound to UploadTargetFolder, which gets updated whenever we switch into this view to ensure that the correct ApplicantGUID is being used for our target

    The commands cover the three things that we need to ensure uploads are going as planned and reporting status back to the UI. UploadStarted will let us know, if you haven't guessed, when the upload is starting. UploadFinished is doing the same when the upload finishes, except this lets us grab the instance of RadUpload so that when FileUploadFinished runs, we know which property of the entity to 'attach' the file to. I won't go into the EventClass code (it's the same for every command I add like this, albeit with names and control references switched up), but here are the three EventBehaviors:

        publicclassUploadStartedEventBehavior : CommandBehaviorBase<RadUpload>
        {
            publicUploadStartedEventBehavior(RadUpload element)
                : base(element)
            {
                element.UploadStarted += newEventHandler<UploadStartedEventArgs>(element_UploadStarted);
            }
      
            voidelement_UploadStarted(objectsender, UploadStartedEventArgs e)
            {
                RadUpload ru = sender asRadUpload;
                base.CommandParameter = ru.Name;
      
                base.ExecuteCommand();
            }
        }
    ...
        publicclassUploadFinishedEventBehavior : CommandBehaviorBase<RadUpload>
        {
            publicUploadFinishedEventBehavior(RadUpload element)
                : base(element)
            {
                element.UploadFinished += newEventHandler<EventArgs>(element_UploadFinished);
            }
      
            voidelement_UploadFinished(objectsender, EventArgs e)
            {
                RadUpload ru = sender asRadUpload;
                base.CommandParameter = ru.Name;
      
                base.ExecuteCommand();
            }
        }
    ...
        publicclassFileUploadedEventBehavior : CommandBehaviorBase<RadUpload>
        {
            publicFileUploadedEventBehavior(RadUpload element) 
                : base(element)
            {
                element.FileUploaded += newEventHandler<FileUploadedEventArgs>(element_FileUploaded);
            }
      
            voidelement_FileUploaded(objectsender, FileUploadedEventArgs e)
            {
                base.CommandParameter = e;
                  
                base.ExecuteCommand();
            }
        }

     

    and their respective DelegateCommands on the viewmodel:

    // When upload starts we update the UI
    publicvoidUploadStartCommand(objectobj)
    {
        stringcontrolName = (string)obj;
        if(controlName.Contains("Resume"))
        {
            ResumeUploadStatus = "Started";
        }
        elseif(controlName.Contains("CoverLetter"))
        {
            CoverLetterUploadStatus = "Started";
        }
        else// only one left is Project
        {
            ProjectUploadStatus = "Started";
        }
    }
    // Same when upload finishes
    publicvoidUploadFinishCommand(objectobj)
    {
        stringcontrolName = (string)obj;
        // save this to use in FileUploadFinishCommand
        _uploadName = controlName;
        if(controlName.Contains("Resume"))
        {
            ResumeUploadStatus = "Complete";
        }
        elseif(controlName.Contains("CoverLetter"))
        {
            CoverLetterUploadStatus = "Complete";
        }
        else// only one left is Project
        {
            ProjectUploadStatus = "Complete";
        }
    }
    // Use this to capture the file name on upload finishing :)
    publicvoidFileUploadFinishCommand(objectobj)
    {
        FileUploadedEventArgs uploadEvents = obj asFileUploadedEventArgs;
        stringuploadFileNameResult = uploadEvents.SelectedFile.Name;
        if(string.IsNullOrEmpty(uploadFileNameResult))
        {
            eventAggregator.GetEvent<NotifyUserEvent>().Publish("Problem uploading file!");
        }
        else
        {
            if(_uploadName.Contains("Resume"))
            {
                ActiveApplicant.Resume = "/HR/applicants/"+ ActiveApplicant.ApplicantGUID.ToString() + "/"+ uploadFileNameResult;
            }
            elseif(_uploadName.Contains("CoverLetter"))
            {
                ActiveApplicant.CoverLetter = "/HR/applicants/"+ ActiveApplicant.ApplicantGUID.ToString() + "/"+ uploadFileNameResult;
            }
            else// only one left is Project
            {
                ActiveApplicant.OverviewProject = "/HR/applicants/"+ ActiveApplicant.ApplicantGUID.ToString() + "/"+ uploadFileNameResult;
            }
            _uploadName = "";
        }
    }

     

    So the order of events is:

    • Upload Starts - Update UI
    • Upload Finishes - Update the UI and save RadUpload instance name
    • File Upload Finishes - Save the file name and location to our entity

    Lastly we have the HyperlinkButton, which utilizes *UploadStatus as a tracking variable on the viewmodel to determine where we are at with our upload (and if we have one when loading an Applicant in), the foreground gets converted to show successful (green), standard (black), or error (red) states, and the NavigateUri points to the file that is accessible on the server.

    So what happens here? Let me give you a short pictorial to show you how this all goes down...

    RadUploadProcess

    And we're good to go. :)

    Next week we cover the (I hope) significantly easier approach of doing this all in the code-behind version.

    Cheers!

    Building a Data Warehouse Part III: Location of your data warehouse

    $
    0
    0

    [repost from Stephen Forte's Blog]  

    See also:

    In Part I we looked at the advantages of building a data warehouse independent of cubes/a BI system and in Part II we looked at how to architect a data warehouse’s table schema. Today we are going to look at where to put your data warehouse tables.

    Let’s look at the location of your data warehouse. Usually as your system matures, it follows this pattern:

    • Segmenting your data warehouse tables into their own isolated schema inside of the OLTP database
    • Moving the data warehouse tables to their own physical database
    • Moving the data warehouse database to its own hardware

    When you bring a new system online, or start a new BI effort, to keep things simple you can put your data warehouse tables inside of your OLTP database, just segregated from the other tables. You can do this a variety of ways, most easily is using a database schema (ie dbo), I usually use dwh as the schema. This way it is easy for your application to access these tables as well as fill them and keep them in sync. The advantage of this is that your data warehouse and OLTP system is self-contained and it is easy to keep the systems in sync.

    As your data warehouse grows, you may want to isolate your data warehouse further and move it to its own database. This will add a small amount of complexity to the load and synchronization, however, moving the data warehouse tables to their own table brings some benefits that make the move worth it. The benefits include implementing a separate security scheme. This is also very helpful if your OLTP database scheme locks down all of the tables and will not allow SELECT access and you don’t want to create new users and roles just for the data warehouse. In addition, you can implement a separate backup and maintenance plan, not having your date warehouse tables, which tend to be larger, slow down your OLTP backup (and potential restore!). If you only load data at night, you can even make the data warehouse database read only. Lastly, while minor, you will have less table clutter, making it easier to work with.

    Once your system grows even further, you can isolate the data warehouse onto its own hardware. The benefits of this are huge, you can have less I/O contention on the database server with the OLTP system. Depending on your network topology, you can reduce network traffic. You can also load up on more RAM and CPUs. In addition you can consider different RAID array techniques for the OLTP and data warehouse servers (OLTP would be better with RAID 5, data warehouse RAID 1.)

    Once you move your data warehouse to its own database or its own database server, you can also start to replicate the data warehouse. For example, let’s say that you have an OLTP that works worldwide but you have management in offices in different parts of the world. You can reduce network traffic by having all reporting (and what else do managers do??) run on a local network against a local data warehouse. This only works if you don’t have to update the date warehouse more than a few times a day.

    Where you put your data warehouse is important, I suggest that you start small and work your way up as the needs dictate.


    Telerik AJAX Q1 2011 Service Pack 2

    $
    0
    0

    The next stabilization release of the Telerik AJAX controls has just been shipped. To see what is included in this wrap up, visit the quick links below:

    RELEASE NOTES / LIVE DEMOS / ONLINE DOCUMENTATION

    TRIAL DOWNLOAD / PAID DOWNLOAD

    Although there is nothing flashy in this service pack, there a few noticeable additions/improvements that are worth to be mentioned explicitly, hence I am giving them in a "digested" form:

    ServicePack_image3
    • AsyncUpload - added functionality to set TemporaryFolder globally using the appSettings section in web.config
    • Calendar - added a quick option to enable Today's day highlighting via RadCalendar's SmartTag
    • Grid - introduced a new property (RadGrid.ClientSettings.DataBinding.ShowEmptyRowsOnLoad) to provide the option to hide empty data rows on initial load with client-side data-binding
    • Input - added Display property for all RadInputs
    • RibbonBar - a bunch of new properties and methods have been included (see release notes)
    • Rotator - added a Target attribute to the RadTickerItem in order to specify the target attribute when NavigateUrl is defined
    • Scheduler - improved RadScheduler's RecurrenceEditor to support clean initialization with no/empty RecurrenceRule
    • TreeList - handlers on server for some client fired commands are implemented

    Next objective > Q2 2011 AJAX Beta release in the end of June, stay tuned.

    Using the Multiple Selection of the RadCalendar control for Silverlight and WPF with MVVM

    $
    0
    0

    Developing and supporting MVVM applications is easy and effective. That's why we want to create MVVM applications that follow this pattern. Sometimes the controls we use have some limitations. For example, list properties, which are read-only and do not allow us to create an appropriate binding to our view-models. It is normal for properties of list type to be read-only, because this is considered a good practice, but it becomes a problem for the MVVM pattern. In the ItemsControl this problem is solved with two properties - Items and ItemsSource. This blog post is about an example that demonstrates how to create an additional property for the SelectedDates property of the RadCalendar control.

    Here is the demo application:

     

    Get Microsoft Silverlight

     

    And the code of the main page is as follows:

    <UserControlx:Class="CalendarAndViewModel.MainPage"
        xmlns:local="clr-namespace:CalendarAndViewModel"
        mc:Ignorable="d"
        d:DesignHeight="300"d:DesignWidth="400">
        <UserControl.DataContext>
            <local:SampleViewModel/>
        </UserControl.DataContext>
     
        <Gridx:Name="LayoutRoot"Background="White">
            <Grid.RowDefinitions>
                <RowDefinitionHeight="25"/>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
             
            <StackPanelOrientation="Horizontal"Grid.Row="0">
                <ButtonContent="Select many"Click="OnSelectManyClick"/>
                <ButtonContent="Deselect all"Click="OnDeselectAllClick"/>
            </StackPanel>
             
            <telerik:RadCalendarGrid.Row="1"
                                 SelectionMode="Extended"
                                 local:CalendarExtensions.TrackCalendarSelectedDates="True"
                                 local:CalendarExtensions.SelectedDates="{Binding SelectedDates, Mode=TwoWay}"/>
     
            <ListBoxGrid.Row="2"ItemsSource="{Binding SelectedDates}">
     
            </ListBox>
        </Grid>
    </UserControl>

     

     

    The details of the implementation process are not a subject of this article, so I will just share the project here. If interested, you can download it from here.

    Using the TeamPulse Ideas & Feedback Portal on Your Smartphone or Tablet

    $
    0
    0

    I love mobile computing. A lot of innovation has emerged in this area lately with Microsoft's WP7 Mango, Apple's iOS 5 and Google's Ice Cream Sandwich all making waves in the last few months. The devices that these operating systems power have become an important part of many people's daily routine. I myself just recently spent close to 1,000 dollars on a new smartphone, justifying it to my spouse by arguing that I spend more time on my phone then I do on my computer (Not quite true, but let's keep that our little secret, shall we?).

    The great thing about these devices is that they keep us connected to our tools even when we're not in the office. This is critical because work often doesn't fit neatly into a 9-to-5-sitting-at-my-desk box. That's one of the reasons I'm very excited about our new TeamPulse Ideas & Feedback Portal. With this new tool, people can register their ideas and feedback no matter where they are. Your customer could be viewing your application on her tablet (regardless of the operating system), then without having to wait, jump over to our portal and provide her feedback while it's fresh in her mind. Does your head of sales want to capture the two or three great feature requests he just heard about during a sales visit while he's thinking of it? No problem. Instead of sending an email that someone will have to copy into TeamPulse, he can simply open up the portal on his phone and place the item there himself. Zero friction access.

    Our new Ideas & Feedback Portal is completely mobile compatible. As you can see in the video, the portal lives happily inside my iPad (or any other tablet or smartphone). As the TeamPulse product owner, I can now perform the important activity of managing feedback from our customers, all from the comfort of my favourite mobile device.

    Try as part of TeamPulse



    Learn more >>

    What to do when team members go dark, aka the problem with “Fine”

    $
    0
    0

    We’ve all heard it in our personal relationships, whether it’s a partner, parent, or child.  You ask a question, and the dreaded answer comes – “Fine”.  What’s wrong with that answer, you ask?  It’s not the word.  It’s the deep ambiguity behind it.  What I have learned in 15 years of marriage is that there is always a story behind that simple word, and have learned how to probe to find it.

    Think about this in your work environment.  One of the problems with the traditional (or waterfall) development methodology is a lack of continuous, structured communication.  Oh sure, there might be status reports (written or verbal), or periodic meetings, but what do you usually hear from the team members? “It’s fine.” This can continue on until the team gets closer to the release, then all of a sudden, problems start “appearing” where before everything was just “fine”.

    How can this happen?  Why didn’t the team just bring up their impediments or issues when they appeared, instead of waiting until the last minute?  Were they hiding them?  Not likely.  People aren’t generally deceitful.  More likely, they were overly optimistic.  Sure, they had issues. But there was plenty of time in the schedule to make up for them, right?  It’s easier to just report “Fine” than to raise the alarm and draw attention to your self.

    Typically, if a coworker tells you everything is fine, you just accept it and move on.  It’s in our personal relationships that we’ve learned the subtleties of that word.  We don’t typically have the type of relationship with our coworkers that would cause us to question someone who declares that everything is “fine”.  But what if things aren’t really fine, but your coworker still reports their status as fine?

    It’s happens all too often – team members are going through a drop in productivity (for a variety of reasons), yet they don’t report it.  Those issues might be blocking bugs, overly optimistic estimates, or simply a lack of experience.  They might not think the issues are a big deal, or they maybe afraid to bring them up to the team for fear of repercussions or embarrassment.  Maybe they have some personal items that are interfering with their productivity that they want to keep personal.

    In development, we call this “Going Dark”.

    How does a team expose when one or more developers go dark? You might say that communication is the key. Only by increasing communication amongst the team can we get a better understanding of the pulse of the project. However, if a developer doesn’t want to come forward with their issues, having a standup isn’t going to fix that problem.

    Then burn down charts are surely the answer!  As I’ve always said, before you can fix anything, you have to expose it and measure it.  That is true, but just injecting standups and burn down charts into your development process alone doesn’t necessarily surface when developers go dark.  Take the burn down chart shown in Figure 1.  There is definitely a problem with the project, and it’s been going on for several days.  But what is the problem?  It’s impossible to tell.  Maybe in the standup, the team has been stating what is holding them back. Then again, maybe not.  If they are still reporting that nothing is holding them back (“Everything is fine”), then it’s a classic case of developers (maybe the whole team) going dark.

    image

    Figure 1 (Image from Telerik’s TeamPulse Agile Project Management Software)

    If the problems aren’t being raised in the standups (or maybe your team isn’t holding daily standups), the only indicator of developers going dark is a drop in velocity.  Even worse, if the problems aren’t caught early enough, they can lead to missed deadlines and cost overruns. If your team is working in sprints and using burn down charts (and more importantly, keeping them up to date and accurate), the problem becomes apparent before the deadline is missed.  The scrum master/project manager knows to dig into the project to see what’s going on.  But where to start?  Do you spend the time and energy probing every team member? Do you have the resources for that?

    What we need are personal burn down charts so the scrum master/project management can quickly see who’s gone dark, and not have to spend the time trying to interpret whether “Fine” means “Fine” or “I’m totally in the weeds here!” Something like the People Status screen shown in Figure 2 would help to take all of the guesswork out the equation and simple show that three of the team members have “gone dark”. Red lines indicate nothing being produced. Not completing any tasks on a single day might not be that bad (it all depends on how your team sizes tasks), but several days in a row certainly indicates a problem.

    image

    Figure 2 (Image from Telerik’s TeamPulse xView™ )

    We need to keep advancing our transparency if we want to keep advancing our teams.  The more low-friction tools we have at our disposal the better we can manage all aspects of our projects.  Communication is hard.  If it was easy, we would all be doing it so much better, and we would need to incorporate processes into our lives to facilitate it.

    Remember – Fine isn’t always fine.  If you ask someone how their day is, and they answer “Fine”, and you truly care how their day is, you need to dig deeper.  But when their day really is “fine”, than digging deeper is a waste of precious time, and moreover, can lead to problems (like feelings of mistrust) between team members.

    If someone asks you how things are going, don’t answer with “Fine”.  Tell them specifically.  “It’s going pretty well, we are still on track” or “We’ve hit some snags, but we will be able to make our deadlines” can both be distilled down to “Fine”.  After all, both groups will probably hit their mark and make their commitment, but the latter case would warrant some extra love from the project manager…

    Happy Coding!

    XAMLflix Video–RadTimeBar for Silverlight and WPF

    $
    0
    0

    This week on XAMLFlix we’re looking at RadTimeBar for Silverlight and WPF.

    XAMLflix is a Telerik production, designed to teach you how to use and get the most out of new new and existing controls in Telerik’s XAML suite.  Every Tuesday and Thursday we have new videos; every Wednesday we have a new written tutorial. 

    Since the Telerik Silverlight and WPF controls share a common codebase and API, you only have to learn how to use them once! In this video we show how to work with RadTimeBar in Silverlight, but the downloadable code demonstrates clearly that the same code works perfectly in WPF.

    RadTimeBar is a lightweight time-bound Data Visualization control. It acts as a container for displaying data, and is ideally suited to work with RadSparkline, containing the Sparkline and giving it context within a time period. You can also combine RadTimeBar with RadChart, RadGridView, RadBulletGraph etc.

    RadTimeBar provides a powerful context for RadSparkline. The sparkline is terrific at providing an overview of the trends of your data; anchoring it in RadTimeLine gives that overview a context of when the various changes occurred.

    • RadTimeBar Getting Started introduces the RadTimeBar and shows you how to create one declaratively – that is, within XAML.  It also introduces the concepts of intervals, such as month, week and day to enhance your display. Finally the video shows you how to control how much of the time line is initially displayed. (Download the project!)
    • RadTimeBar Code shows how to create a RadSparkline and a RadTimeBar in C#. By taking programmatic control over the creation and display of the control you gain the ability to modify the appearance of the control dynamically. The properties set programmatically are of course the same as those set declaratively in XAML.  (Download the project!)
    • RadTimeBar Advanced Features dives more deeply into managing the amount of data that is initially displayed. Three time spans are considered: the time for the entire display, the time span initially shown in the control and the time span for the selection.  Additionally, a new attribute is introduced that allows you to have the highlighted span snap to time intervals. (Download the project!)

    Wrap-Up

    Telerik XAMLflix for WPF controls In these videos you’ll see how easily you can add and modify RadTimeBar and how you can use RadTimeBar as a container for other data visualization controls such as RadSparkline.

    Remember, RadTimeBar is only one of the controls offered in the Silverlight/WPF suite. Download your own copy of the Silverlight and WPF control suite right now.  

    What would you like to see us cover in this series? Are there particular controls or details of controls you’d like to see XAMLflix videos on? Just add a comment.

    The next trick in Add OpenAccess Service Wizard sleeve - Web API

    $
    0
    0

    Telerik OpenAccess ORM Q2 2012 is already live so hurry up and check all the benefits of upgrading to it on our What’s New page

    One of the most interesting additions to this release is the Add OpenAccess Service wizard (in short AOS wizard), a great time-saver when you want to expose your data to other tiers using various kinds of services. After implementing the generation of WCF Data Services 5 there, we would like to share with you our future plans for this wizard – Web API support!

    Goals

    As many of you know Microsoft recently published a release candidate version of the new WebAPI with the MVC 4 RC. We think it is the perfect moment to add one more service layer technology to the broad array of service types generated by AOS wizard.
    As with the other service scaffolds, the main goal is to let developers hit the ground running with a new service implementation. That means we need to expose endpoints for each entity, and related methods for creating, updating and deleting them. In the case of WebAPI, we will also need to configure service routes in the global.asax.

    Challenges

    The WebAPI framework makes it easier for developers to create and configure a service layer for any application, but some of the same challenges must still be faced. In particular, how do you best expose your data at the service boundary?

    In a well-designed data model, entities have many relationships which can wreak havoc on a JSON or XML serializer. To get around these issues the Add OpenAccess Service Wizard creates repositories and DTOs for each entity. While we believe separating the data layer and the transport layer is a good thing, we consider allowing the developers to make that decision based on their specific needs. We will provide an option for that.

    As always, the AOS wizard will generate the service end points using T4 templates, which can easily be customized. That said, we hope that by starting the conversation early we can make the default functionality robust enough that most developers will not have to customize anything :)

    Conclusions

    In the end it is YOUR feedback that matters most!

    What would you like to see the Data Service Wizard scaffold for WebAPI out of the box?

    Are you going to replace any of your existing WCF services with WebAPI?

    Would you like to see navigation properties support in our DTO types in the WebAPI service layer?


    Happy Coding!

    Getting Started with JustCode Webinar

    $
    0
    0

    Telerik JustCode includes many features beyond what is offered in a vanilla installation of Visual Studio. More importantly, it gives you these features without interfering with the way you code. The latest edition includes a Getting Started Wizard to help you learn the basic features of JustCode. Even so, any extremely powerful tool deserves a good walk-through.

    On Tuesday, July 3rd, join the Getting Started with JustCode Webinar, where I will do just that.

    Attend this webinar to discover awesome features you can use immediately and how JustCode makes your work day easier. Along the way, I will show you a few neat tricks so you’re never stuck. 

    This webinar is for everyone, and I will be taking audio questions at the end. If you’re available this Tuesday at 9am EDT, please register here

    Due to the lack of progress in molecular assembler technology, refreshments will not be provided. 

    Hope to see you there, and happy coding! 


    A Brief Guide To Data Manipulation with Telerik’s mighty PivotGrid for ASP.NET AJAX

    $
    0
    0
    Since we introduced the RadPivotGrid for ASP.NET AJAX in Q2 2012 we have been working hard to bring new functionalities and make our next grid control the best on the market. Now with the release of Q3 2012 we are happy to tell you that we are even closer to achieve desktop-like experience in the browser. The new Telerik’s PivotGrid ConfigurationPanel is a perfect showcase of what RadControls could do and how the web could encapsulate rich client-side interactions with heavy CPU intensive backend calculations. Let’s go through the details.

    Telerik’s PivotGrid ConfigurationPanel

    ConfigurationPanel basics - separation between data and field manipulations

    The panel is perfect when you need to make a clear distinction between data and logic. In scenarios where lots of field manipulations are required - reordering, showing, hiding, sorting and filtering data, the configuration panel conveniently separates these operations from the table which display the data which improves user experience and provides easier learning curve for the end user.
    But everything you read so far comes at a price – a RadPivotGrid EnableConfigurationPanel property should be set to true ;). The panel demo perfectly showcases the idea and everyone interested could try it out here

    Moving things around

    The fun part is when you start dragging and dropping items around. Of course, that is not the only way to move fields. You could also use the convenient Telerik’s ASP.NET ContextMenu. All functionalities could be toggled by Boolean properties under the RadPivotGrid.ConfigurationPanelSettings. Try it out! I bet you will like it and feel the intuitive interface.

    Layouts and positioning

    You have the freedom to position the panel at five places in four different layouts. This makes whole twenty variants if my school teacher has taught me right :). I recommend you to place the panel in the Fields RadWindow so you could use the whole page for displaying the important data and leave the floating window to do the rest.

    Defer Layout Update

    “Defer Layout Update” is a mode, part of the many features the ConfigurationPanel introduces. It will give you the opportunity to boost performance by queuing operations. Page postback occurs only when the Update button is clicked. The functionality is very useful when a lot of field manipulations are required.

    What’s next

    Try the feature yourself to get your own impressions of it. The documentation here will surely help you throughout the process. We are waiting for you feedback.

    Keep an eye on our releases because we are not done yet. We will bring lots of new functionalities and improvements for the next release to all our controls. So be in touch!

    Cloudy with a Chance of Testing

    $
    0
    0

    Greetings, Testers. Over the past several weeks, we've been talking about four technology trends that have been identified as disruptive, and Peter & I discussed them in our recent webinar.

    For example, there's the cloud, "a colloquial expression used to describe a variety of different types of computing concepts that involve a large number of computers connected through a real-time communication network such as the Internet." [wikipedia's description] In real terms, for us that means one or more virtual systems that we can use to host our data or applications without adding IT staff or hardware in our own racks. What we give up in direct control, we often gain in reduced cost and increased flexibility.

     

    Telerik's tools give developers and testers several ways to take advantage of cloud computing.

    For mobile developers, Icenium Everlive gives you several options for data storage, code execution & more, and Icenium Mist is a cloud based IDE for developing hybrid mobile applications. You can code, test (through a device simulator) and build your entire hybrid mobile app through your browser. Icenium also supplies cloud based build services for iOS and Android, along with deployment to the app stores for each, regardless of which Icenium IDE you're using.

    You can easily add EQATEC Analytics to your applications, and get application analytics, error reporting, and more, all through cloud based services.

    Test Studio for iOS users can take advantage of our web portal for collaboration and storage of tests & result data.

    Testers who are using Test Studio for functional or load testing can set up execution servers on remote servers on a cloud-based application environment. Those can be used to spread the testing across lower-cost virtual systems, as long as they can access the systems you're testing of course, and the tests can be scheduled to run whenever convenient.

    How are you leveraging cloud computing as part of your development and testing processes? Comment here or join in the conversation on Twitter. And as always, if you're not already using Test Studio, there's a 30-day free trial waiting for you.

    Peace,
    Steven

    About the Author

    picture of Steven Vore

    Steven Vore

    Steven Vore is an Evangelist for Telerik's Test Studio. He has worked in software support and testing for the better part of two decades, and enjoys exploring ways to make software easier to use. He is a fan of movies and music, and can often be found on Twitter as @StevenJV.

    Telerik DevCraft Q1 2015 Webinar – WrapUp & Road Ahead

    $
    0
    0

    On Wednesday March 11, Telerik hosted the DevCraft Q1 2015 Release webinar–and boy, it was fun. At your service delivering the webinar were the trio of aspiring .NET ninjas, just like all of you: Michael Crump, Ed Charbeneau and Sam Basu. We thoroughly enjoy talking to fellow developers and hope it was just as much fun for you. Let’s recap a little.

    First, huge thanks to everybody who joined our webinar, taking time from your busy day. Hosting thousands of developers in a live webinar always runs the risk of running into technical issues, thankfully everything was smooth. And just as promised, the webinar was recorded in its entirety. So, in case you missed the DevCraft Q1 Release webinar or if you just want to revisit the topics covered, the video recording is up on YouTube.

    If you wanted to catch up on some of the content we used during the webinar, here are some resources that you may find helpful:

    1. Sam’s slide deck | Sam’s Demo code (demo included in installer)
    2. Michael’s slide deck | Michael’s Demo code
    3. Ed’s slide deck | Ed’s Demo code
    4. What’s new in Telerik UI for Windows Universal
    5. What's new in Telerik UI for ASP.NET Ajax
    6. Updates in Telerik UI for Xamarin
    7. Telerik Report Server

    The other fun aspect of DevCraft webinars is all the questions we get from all of you. You’re passionate about DevCraft and have a stake in its product features/roadmaps – we get it. We love hearing first-hand developer success stories or pain points, and questions during DevCraft webinars help flush those out. This quarter was no different with hundreds of enthusiastic questions from all of you.

    A special thank you goes out to two Telerik Product Managers: Nikolay Diyanov and Iana Tsolova, who joined the webinar behind the scenes and helped answer many of your questions, as fast as they could type. In addition to answering your questions through the typed question panel, we did about 10 minutes of voice Q/A at the end of the webinar. We hope that it was helpful, but realize it is barely enough.

    So, in order to do justice to all of your love and questions, we’re doing something new for this DevCraft Q1 release. Post-webinar, we’ll do a couple of informal Google Hangouts to answer each and every one of your questions. In addition, we realize that we cram a lot of product news in our one hour DevCraft webinar time. So, how about we take some extra time to showcase some new product features or deep-dive into solutions that we just did not have time for during the webinar? You’ll want to join in on the fun, right? We have two upcoming Google Hangouts on Air already scheduled – simply show up. We’re calling them Telerik DevCraft Release Tech Chats:

    Ok, now let’s cut to the chase and declare the prize winners from our DevCraft Release webinar--you just can’t wait, can you? We don’t blame you with such craved-after tech gadgets up for grabs. So here are the lucky winners – randomly selected, just for joining our webinar:

    1. XBox One – Venkata Reddy Vatrapu
    2. Nokia Lumia 930 (unlocked) – Brad Gonzalez
    3. Apple iPhone 6 (unlocked) – Ratna Dabbiru

    And as promised, the person with the best (and most thoughtful/technical/relevant) question gets to take home something that is hard to lay your hands on: a Microsoft Band. The best question adjudged winner is,“Is it possible to add your own custom animation to SideDrawer control?” by Paresh Nawale. The answer is : Yes. In a Xamarin.iOS/Xamarin.Android project with the Xamarin.iOS/Xamarin.Android wrapper  it is possible to add your custom animation.

    Congratulations to all of our winners.

    We can't wait to see what you build with the new products and feature enhancements now available in Telerik DevCraft. Make sure to get the latest bits. Have fun & happy coding!

    Reverse Mapping and Using Database Views with Telerik OpenAccess ORM

    $
    0
    0

    We are glad to announce that one of the major improvements for our 2009 Q2 release is the support for database views.

    Views are stored queries accessed as virtual tables which represent the result of a query. To provide higher security, they can encapsulate the data into smaller result sets accessible from particular roles. Views are also used to combine data from many tables and allow the developer to expose the table data to the user in a more natural manner. Performance optimizations for fast searching and reading can be accomplished as well when using indexed views.

    Now with Telerik OpenAccess ORM you can reverse map views to classes the same way you do with regular tables. And that is not all, the data exposed by the views can be even modified and stored back to the database.

    This post is to guide you through the initial steps of mapping database views. We assume that your project is already “Enabled” to use Telerik OpenAccess ORM and the database connection is properly configured. If you are trying our product for the first time, this step-by-step how-to will help you to understand the process.

    You can also use the already mapped Northwind model from our Code library. In order to run it, please remove and add again the Telerik.OpenAccess and Telerik.OpenAccess.Query references. Then run the Reverse mapping wizard and click the “Merge” button. This will add the information necessary to map the views available in the database.

    We are now going to map the “Alphabetical list of products” view from the Northwind database. It contains columns from two related tables – Products and Categories.

    ProductsView

    Step 1: Open the Reverse Mapping wizard

    Step1

    The Simple View tab shows all available tables and views from the database along with some basic options needed to create the code. Each table/view can be mapped to a Class, Collection or Map. Usually collections and maps are used for mapping join tables. When mapping views, choose the Class option. Here you can also specify custom class and namespace names.

    Step 2: Switch to Advanced View.

    Step2

    The Advanced View tab provides options that are not available in the Simple View but are necessary to map successfully a view. Select the Views node from the Treeview. A grid similar to the one from the previous step shows up. Now you have to choose which views to be mapped. To do this, enable the relevant “Generate” checkbox next to each. You may notice that the treeview icons have been changed for the views which are marked to be mapped.

    Step 3: This step is specific for mapping views. They do not provide information about identity columns as the regular tables do. However, all persistent classes generated by Telerik OpenAccess ORM require an identity field. In this context, we have to manually set this identity for each class. Expand the view name in the treeview and select the id field (in our case “ProductID”). Then enable the “Primary Key” checkbox on the right. After setting an identity, the red warning about missing primary key field should disappear from the code preview window. Note that views without primary key columns are not currently supported. The uniqueness of each row is required for write operations and proper usage.

    NOTE: It is user’s responsibility to set a real primary key – in the case where no real identity column is included in the view, you should use a composite key developed by including multiple columns from the available, trying to produce unique combination – usually meaning that all of the columns should be marked as such.

    Step3

    Step 4: When you have chosen identity fields for all classes, they are ready to be generated. Click the “Generate & Save Config” button.

    After the classes are created you can use them to retrieve and modify the data as you have used to do with classes mapped to tables. To illustrate the basic read and update operations, we will use the already mapped “Alphabetical list of products” view. Currently create and delete operations are not supported for views containing columns from more than one table.

    Both OQL and Linq queries can be used to fetch data:

    Linq:

    AlphabeticalListOfProduct product = (from x in scope.Extent<AlphabeticalListOfProduct>()
                                                               
    where x.ProductID == 1
                                                               
    select x).First();

    OQL:

    string queryStr ="SELECT * FROM AlphabeticalListOfProductExtent as a WHERE a.ProductID == 1";
    AlphabeticalListOfProduct product = scope.GetOqlQuery<AlphabeticalListOfProduct>(queryStr).ExecuteEnumerable().First();
     

    Updating data is easy as usual. Even the referenced object can be changed, just make sure changes are made within an active transaction:

    scope.Transaction.Begin();
    product.ProductName ="Cheese";
    product.CategoryID = 4;
    scope.Transaction.Commit();

    We believe the ability to reverse map and work with views is crucial for many people and will be useful for the rest of them as well. We are eagerto find out what you think of this feature and to have your feedback.

    The Telerik CAB Enabling Kit and SCSF – Tutorial 2: UIExtensionSites

    $
    0
    0

    Hello everyone, and welcome to the second tutorial in my series of tutorials about the Telerik CAB Enabling Kit (TCEK). This week I will be talking about the UIExtensionSites supported in the TCEK. The TCEK comes with a number of UI Adapters that provide support for the following controls.

    • RadMenu
    • RadToolStrip
    • RadPanelBar
    • RadTreeView

      These controls are supported through the registration of custom Adapter Factories and Command Adapters. Adapter Factories simplify the task of creating custom UI Adapters for individual controls. Command Adapters allow you to add invokers and/or set command status on specific controls. In the last tutorial, we created a TCEK enabled project, and through having done this, these adapters are now registered for us on program startup.

      In this tutorial, we will be focusing on the RadMenu and RadToolStrip. The program we will be creating is a simple “asset management” application that contains a RadMenu, RadToolStrip, and RadGridView as its core components. The RadMenu and RadToolStrip are created in the main ShellLayoutView and are registered as UIExtensionSites. The RadGridView is the main component in the AssetManager module. The AssetManager module registers  RadMenuItems and RadButtonElements with the UIExtensionSites to allow for control and manipulation of the RadGridView through CommandHandlers.

      Program Screenshot

      Figure 1. The Asset Management Application

      I am going to start with the TCEK Enabled project I created in tutorial 1. If you don’t have the source to that project, you may download it here. Also, if you have not yet had a chance to read through the first tutorial, you may do so by going here. Lets get started!

      Setting Up the ShellLayoutView

      In this series of steps, we will create the ShellLayoutView. This view is the primary view of our application. It will contain the main workspace, RadToolStrip, and RadMenu. The RadToolStrip and RadMenu will be the primary UIExtensionSites used throughout the program.

      1. Open the TCEK Enabled project in Visual Studio.
      2. Expand the Infrastructure.Layout project and double click ShellLayoutView.cs to open it in the designer.
      3. Select and delete all of the controls in the design view except for the DeckWorkspace control named _rightWorkspace.
      4. Place _rightWorkspace in a RadPanel and rename it to _mainWorkspace.
      5. Drag a RadMenu and a RadToolStrip into the designer.
        1. Delete the radToolStripItem1 from the Toolstrip.
      6. Right click ShellLayoutView.cs and select View Code.
        1. Remove the line of code that assigns the left workspace.
        2. Refactor the WorkspaceNames.RightWorkspace constant to be named WorkspaceNames.MainWorkspace.
          public ShellLayoutView() 
              InitializeComponent(); 
              _mainWorkspace.Name = WorkspaceNames.MainWorkspace; 
           
        3. Remove all unnecessary method and properties such as MainStatusStrip, OnFileExit(), and SetStatusLabel().
        4. Update the MainMenuStrip, and MainToolbarStrip properties to return the RadMenu and RadToolStripElement.
          internal RadMenu MainMenuStrip 
              get { return radMenu1; } 
           
          internal RadToolStripElement MainToolStrip 
              get { return radToolStripElement1; } 
      7. Double click ShellLayoutViewPresenter.cs to view it’s code.
        1. Remove the method that subscribes to the StatusUpdate event.
        2. Remove the OnFileExit() method.
        3. Update the OnViewSet() method to register the RadMenu and RadToolStrip controls as UIExtensionSites.
          protected override void OnViewSet() 
              WorkItem.UIExtensionSites.RegisterSite(UIExtensionSiteNames.MainMenu, View.MainMenuStrip); 
              WorkItem.UIExtensionSites.RegisterSite(UIExtensionSiteNames.MainToolbar, View.MainToolStrip); 
      8. The ShellLayoutView is now ready.

      Extending the TCEK

      The items used in the RadToolStrip do not support command invokers by default. In this series of steps, we will extend the TCEK to support this feature. We will accomplish this by creating a new RadElementCommandAdapter that supports the base class of items used in the RadToolStrip. This is actually a very simple task and you can probably use the knowledge you gain here to extend support to various other Telerik controls.

      1. In the Solution Explorer, expand the Telerik.CAB.WinForms project.
      2. Expand the Commands folder.
      3. Right click RadMenuItemCommandAdapter.cs and select Copy.
      4. Right click the Commands folder and select paste.
      5. Rename the copy to RadElementCommandAdapter.cs.
      6. Double click RadElementCommandAdapter.cs to view it’s source.
        1. Update the constructors to reflect the name of the file.
        2. Update the second constructor to accept RadElements instead of RadMenuItems.
          public RadElementCommandAdapter() 
              : base() 
           
          public RadElementCommandAdapter(RadElement element, string eventName) 
              : base(element, eventName) 
        3. Update the OnCommandChanged() method to handle RadElements instead of RadMenuItems.
          protected override void OnCommandChanged(Command command) 
              base.OnCommandChanged(command); 
           
              foreach (RadElement element in this.Invokers.Keys) 
              { 
                  if (command.Status != CommandStatus.Unavailable) 
                  { 
                      element.Visibility = Telerik.WinControls.ElementVisibility.Visible; 
                      element.Enabled = (command.Status == CommandStatus.Enabled); 
                  } 
                  else 
                  { 
                      element.Visibility = Telerik.WinControls.ElementVisibility.Collapsed; 
                  } 
              } 
      7. In the Solution Explorer, expand the Application folder.
        1. Double click RadWindowsFormsApplication.cs to view its source.
        2. Register the RadElementCommandAdapter with the ICommandAdapterMapService.
              //Registers Command Adapters. 
              ICommandAdapterMapService mapService = this.RootWorkItem.Services.Get<ICommandAdapterMapService>(); 
              mapService.Register(typeof(RadMenuItem), typeof(RadMenuItemCommandAdapter)); 
              mapService.Register(typeof(RadTreeNode), typeof(RadTreeNodeCommandAdapter)); 
              mapService.Register(typeof(RadElement), typeof(RadElementCommandAdapter)); // this line 
      8. You have now successfully extended the TCEK to support adding invokers to RadElements.

      The AssetManager Module

      In this series of steps, we will create the primary module used in this application. In this module, we will extend the UIExtensionSites with our own custom menu options and toolbar buttons. We will also add CommandHandlers to handle the commands issued by the items added to the UIExtensionSites.

      Creating the Module

      In these steps, we will generate the AssetManager module.

      1. In the Solution Explorer, right click the source folder and select Smart Client Factory->Add Business Module (C#)…
      2. Name the new business module AssetManager and click OK.
        image
      3. Click Finish on the Add Business Module dialog.

      Creating The Data

      In these steps, we will create the object that will hold our “asset” data that is displayed in the grid.

      1. Right click on the AssetManager project and select Add->New Folder
        1. Name the new folder Data.
      2. Right click the Data folder and select Add->Class..
        1. Name the class Asset.
      3. Double click Asset.cs to view it’s source.
        1. Update the source code to contain properties specific to basic information about the assets we will be tracking.
          public class Asset 
              public string Name { getset; } 
              public string Description { getset; } 
      4. Build the project so our Asset class gets compiled into the assembly. This will allow us to easily bind it to a BindingSource later.

      Creating the Command Names

      1. In the Solution Explorer, expand the Constants folder of the AssetManager project and double click the CommandNames.cs file to view its source.
      2. Update the source code to contain the command names we will be using in our view.
        public class CommandNames : CABExample1.AssetManager.Interface.Constants.CommandNames 
            public const string AddAsset = "AddAsset"
            public const string RemoveAsset = "RemoveAsset"
            public const string EditAsset = "EditAsset"

      Extending the UIExtensionSites

      1. In the Solution Explorer, double click the ModuleController.cs file contained in the AssetManager project to view its source.
      2. Extend the MainMenu UIExtensionSite by updating the ExtendMenu() method to contain the following code.
        private void ExtendMenu() 
            RadMenuItem assetMenuItem = new RadMenuItem("Assets"); 
            this.WorkItem.UIExtensionSites[UIExtensionSiteNames.MainMenu].Add<RadMenuItem>(assetMenuItem); 
         
            RadMenuItem addAssetMenuItem = new RadMenuItem("Add Asset"); 
            this.WorkItem.Commands[CommandNames.AddAsset].AddInvoker(addAssetMenuItem, "Click"); 
                     
            RadMenuItem removeAssetMenuItem = new RadMenuItem("Remove Asset"); 
            this.WorkItem.Commands[CommandNames.RemoveAsset].AddInvoker(removeAssetMenuItem, "Click"); 
         
            RadMenuItem editAssetMenuItem = new RadMenuItem("Edit Asset"); 
            this.WorkItem.Commands[CommandNames.EditAsset].AddInvoker(editAssetMenuItem, "Click"); 
         
            assetMenuItem.Items.Add(addAssetMenuItem); 
            assetMenuItem.Items.Add(removeAssetMenuItem); 
            assetMenuItem.Items.Add(editAssetMenuItem); 
      3. Extend the MainToolbar UIExtensionSite by updating the ExtendToolStrip() method to contain the following code.
        private void ExtendToolStrip() 
            RadButtonElement buttonElement = new RadButtonElement("Add Asset"); 
            RadToolStripItem toolStripItem = new RadToolStripItem(); 
            toolStripItem.Items.AddRange(new RadItem[] { buttonElement }); 
            this.WorkItem.Commands[CommandNames.AddAsset].AddInvoker(buttonElement, "Click"); 
            this.WorkItem.UIExtensionSites[UIExtensionSiteNames.MainToolbar].Add<RadToolStripItem>(toolStripItem); 
         
            buttonElement = new RadButtonElement("Remove Asset"); 
            toolStripItem = new RadToolStripItem(); 
            toolStripItem.Items.AddRange(new RadItem[] { buttonElement }); 
            this.WorkItem.Commands[CommandNames.RemoveAsset].AddInvoker(buttonElement, "Click"); 
            this.WorkItem.UIExtensionSites[UIExtensionSiteNames.MainToolbar].Add<RadToolStripItem>(toolStripItem); 
         
            buttonElement = new RadButtonElement("Edit Asset"); 
            toolStripItem = new RadToolStripItem(); 
            toolStripItem.Items.AddRange(new RadItem[] { buttonElement }); 
            this.WorkItem.Commands[CommandNames.EditAsset].AddInvoker(buttonElement, "Click"); 
            this.WorkItem.UIExtensionSites[UIExtensionSiteNames.MainToolbar].Add<RadToolStripItem>(toolStripItem); 

      The AssetListing View

      1. In the Solution Explorer, right click the Views folder of the AssetManager project and select Smart Client Factory->Add View (with presenter)…
        1. Name the view AssetListing. Make sure to check the “Create folder for the view” checkbox, then click Finish.
          image
      2. Double click AssetListing.cs to open it in the designer.
        1. Drag a RadGridView control on the the view and name it AssetListing.
        2. Click the SmartTag on the newly added RadGridView, and in the menu that appears, open the Choose DataSource combobox, then select Add Project Data Source…
          1. Select Object and click Next.
          2. Expand AssetManager, CabExample1.AssetManager.Data, and select Asset, then click Finish.
            image
        3. Update the grid properties to your liking, and so that the grid is read only, and you can not add, delete, or edit new rows.
      3. Double click IAssetListing.cs to view it’s source.
        1. Update the IAssetListing interface to contain properties referencing the RadGridView and the BindingSource.
          public interface IAssetListing 
              RadGridView GridView { get; } 
              BindingSource AssetBindingSource { get; } 
      4. Right click on AssetListing.cs and select View Code.
        1. Implement the IAssetListing interface.
          #region IAssetListing Members 
           
          public Telerik.WinControls.UI.RadGridView GridView 
              get { return radGridView1; } 
           
          public BindingSource AssetBindingSource 
              get { return assetBindingSource; } 
          #endregion 
      5. Double click AssetListingPresenter.cs to view its source.
        1. Create and assign some generic test data to the the AssetBindingSource on the view.
          List<Asset> _assets; 
          public override void OnViewReady() 
              base.OnViewReady(); 
           
              _assets = new List<Asset>(); 
           
              for (int i = 0; i < 100; i++) 
                  _assets.Add(new Asset() { Name = "Asset " + i.ToString(), Description = "Description " + i.ToString() }); 
           
              View.AssetBindingSource.DataSource = _assets; 
        2. Add the AddAsset, RemoveAsset, and EditAsset command handlers. (note: the AssetDetailDialog will be created in the next section)
          [CommandHandler(CommandNames.AddAsset)] 
          public void AddAsset(object sender, EventArgs e) 
              _assets.Add(new Asset() { Name = "New Asset", Description = "New Asset Description" }); 
              View.AssetBindingSource.ResetBindings(false);             
           
          [CommandHandler(CommandNames.RemoveAsset)] 
          public void RemoveAsset(object sender, EventArgs e) 
              Asset asset = (Asset)View.GridView.SelectedRows[0].DataBoundItem; 
              _assets.Remove(asset); 
              View.AssetBindingSource.ResetBindings(false); 
           
          [CommandHandler(CommandNames.EditAsset)] 
          public void EditAsset(object sender, EventArgs e) 
              Asset asset = (Asset)View.GridView.SelectedRows[0].DataBoundItem; 
              AssetDetailDialog detailDialog = new AssetDetailDialog(asset); 
              detailDialog.ShowDialog(); 
      6. Double click ModuleController.cs to view its source.
        1. Update the AddViews() method to add our newly created view to the main workspace.
          private void AddViews() 
              AssetListing view = ShowViewInWorkspace<AssetListing>(WorkspaceNames.MainWorkspace); 

      The Asset Detail Dialog

      1. In the Solution Explorer, Right click the Views folder and select Add->New Folder
        1. Name the folder Dialogs
      2. Right click the Dialogs folder and select Add->Windows Form…
        1. Name the form AssetDetailDialog
          image
      3. Drag two RadLabels from the toolbox into the designer.
        1. Set the Text property of the first label to Name.
        2. Set the Text property of the second label to Description.
      4. Drag two RadTextBoxes from the toolbox into the designer.
        1. Set the text on both of them to be blank.
        2. Select radTextBox1.
          1. In the properties window, expand (DataBindings), then the Text Property.
          2. Locate and expand Asset, then select Name.
        3. Select radTextBox2
          1. In the properties window, expand (DataBindings), then the Text Property.
          2. Expand assetBindingSource and select Description.
        4. Drag a RadButton from the toolbox into the designer.
        5. Set the text on the RadButton to OK.
      5. Set the DialogResult property of the OK button to OK.
      6. Right click the designer window and select View code.
      7. Update the constructor so that it takes an asset and sets it on assetBindingSource.
        public AssetDetailDialog(ref Asset asset) 
            InitializeComponent(); 
            assetBindingSource.DataSource = asset; 

      Conclusion

      Congratulations, you have now created a project that uses the RadMenu and the RadToolStrip as UIExtensionSites! Any CAB based project is a huge effort in itself, so I know how difficult it can be when you need to introduce something new to the bag of tricks. Hopefully this tutorial eased some of that difficulty for you and helped you gain a better understanding of how to use the UIExtensionSites provided by the TCEK with CAB. Next week, I will begin covering the workspaces provided with the TCEK. See you then!

       

      Click here to download the source code used in this post.

      Viewing all 1954 articles
      Browse latest View live