New Features in ASP.NET AJAX 4, Part 2

Instantiating Behaviors and Controls Declaratively

ASP.NET AJAX 4 introduces a way to declaratively instantiate client-side controls and behaviors and attach them to HTML elements. The declarative markup is achieved without adding any new HTML elements, simply by including additional namespaced attributes which are XHTML compliant.

Declarative Instantiation Within a Template

Suppose that you want to add a Contoso.DatePicker control to a div element. In ASP.NET AJAX 4, you can start by declaring a namespace prefix in the opening <body> tag (or in a template's parent tag), similar to the way the @ Register directive works in server-based files. The following example shows a namespace declaration.

<body xmlns:sys="javascript:Sys" xmlns:datepicker="javascript:Contoso.DatePicker">

The javascript:Sys namespace (typically mapped to the sys: prefix, as shown in the example) is used for a number of system attributes. One of those system attributes is sys:attach, which is used to specify a comma-separated list of controls or behaviors to attach to the element, as shown in the following example:

<ul id="myTemplate" class="sys-template">

<li>

<h3>{{ Name }}</h3>

<div>{{ Description }}</div>

<div sys:attach="datepicker" datepicker:date="{{ CreatedDate }}"></div>

</li>

</ul>

The example shows how to instantiate a Contoso.DatePicker control that is attached to a div element and how to set the control's date property to the value of the CreatedDate field of the current data item.

Declarative Instantiation Outside a Template

Declarative instantiation of controls will only work if the declarative markup is within an element that has been configured, or activated, for this purpose. Templates themselves are already activated, so declarative markup to instantiate and attach controls works within a template. But to declaratively instantiate controls outside a template, you must first configure the page to ensure that sys:attach markup is within an activated element. You do this by including a sys:activate attribute on the opening body tag, and setting its value to a comma-separated list of element IDs for the elements that you want to allow declarative instantiation in. The following example activates elements whose IDs are panel1 and panel2:

<body xmlns:sys="javascript:Sys" sys:activate="panel1,panel2">

This causes the ASP.NET AJAX framework to scan the children of those elements for any sys:attach attributes, and to instantiate the corresponding controls.

You can also activate every element in the document. However, doing so can cause a small delay when the page is initialized, so the technique should be used with caution on large pages. The following example shows how to activate the whole document.

<body xmlns:sys="javascript:Sys" sys:activate="*">

A DataView control is typically attached to an element that is not already within a template. This is a common reason to use sys:activate, as in the following complete example:

<body xmlns:sys="javascript:Sys"

xmlns:dataview="javascript:Sys.UI.DataView"

sys:activate="*">

<ul sys:attach="dataview" class="sys-template"

dataview:data="{{ imagesArray }}"

>

<li>

<h3>{{ Name }}</h3>

<div>{{ Description }}</div>

</li>

</ul>

</body>

Live Data Binding

The template examples shown earlier include several examples of data binding that uses the one-way/one-time binding syntax: {{ expression }}. This is illustrated by the following example:

<h3>{{ Name }}</h3>

This type of binding is referred to as one-time binding because the expression is evaluated only once, at the time that the template is rendered. With one-way/one-time binding, if the source data changes after the template has been rendered (in the previous example, if the Name field changes), the rendered value will not be automatically updated.

You can use an alternative live-binding syntax in order to ensure that the target value is automatically updated whenever the source value changes. This is shown in the following example:

<h3>{binding Name}</h3>

With this binding syntax, if the Name field of the current data item is changed, the rendered value will automatically be updated in response.

This example, where the binding is to a text node (the content of the h3 element), illustrates one-way live binding. The source value (in this case, the data) binds one-way to the target (in this case, an HTML text node), so when the source value changes, the target is updated. But there is no binding from the target back to the source.

Another form of live binding is two-way live binding, which is useful when a text box is provided that enables users to modify the value of underlying data, as in the following example:

<input type="text" value="{binding Name}"/>

In two-way live binding, the binding works in both directions. If the target value is changed (in this case, the value in the UI), the source value is automatically updated (in this case, the underlying data item). Similarly, if the source value is changed (in this case, if the underlying data value is updated externally), the target value (the value in the UI) is updated in response. As a result, target and source are always in sync.

In the following example, if the user modifies the value in the text box, the value that is rendered in the h3 element will automatically be updated to reflect the new value that is provided by the user.

<h3>{{ binding Name }}</h3>

<input type="text" value="{binding Name}"/>

The live-binding syntax is similar to binding syntax in WPF (XAML). It can be used for binding between UI and data, as in the above examples, as well as directly between UI elements, between data and properties of declaratively attached controls and components, and so on. The syntax also supports additional features, such as providing functions for converting data values to rendered values, or converting back from values entered in UI to an appropriately formatted data value. The following example shows how to provide conversion functions:

<input type="text" value="{binding Price, convert=toDollars, convertBack=fromDollars}"/>

A similar syntax can be used to specify a binding mode (one-way or two-way) explicitly:

<input type="text" value="{binding Price, mode=oneWay}"/>

However, in most cases this is not necessary, because the default binding behavior is that text boxes and other input controls automatically use two-way binding, and other bindings use one-way binding. In the previous example, this default behavior is overridden so that if the data value changes, the value in the text box will change, but if the user modifies the value in the UI, the underlying data value will not be updated correspondingly.

The underlying technology that enables live bindings is the ASP.NET AJAX observer pattern, which is used internally by the Binding class and is described in the next section. For more information about binding, see The DataView Control later in this document.

Using the Observer Pattern with JavaScript Objects and Arrays

The observer pattern enables an object to be notified about changes that occur in another object. (The term observer pattern is often misused in JavaScript frameworks to describe event handling based on the addHandler method and similar techniques.) ASP.NET AJAX 4 implements the pattern completely. It adds observer functionality to ordinary JavaScript objects or arrays so that they raise change notifications when they are modified through the Sys.Observer interface. (In the present state of JavaScript, changes that are made directly, without going through the interface, will not raise change notifications.) The observer pattern can be used to establish live bindings between UI elements and objects or arrays, such as those you might get from a JSON Web service.

In the following example, the Sys.Observer class is used to add items to the imagesArray array in a way that raises CollectionChanged notifications. As a result, the DataView control will automatically update and display the inserted item after the user has clicked the Insert button. This is possible because the DataView control is bound to its source data (in this case, the imagesArray array that the data property is set to) by using live binding.

<script type="text/javascript">

var imagesArray = [];

Sys.Observer.makeObservable(imageArray);

function onInsert() {

var newImage = { Name: "Name", Description: "Description" };

imagesArray.add(newImage);

}

</script>

<button onclick="onInsert()">Insert</button>

<ul id="imagesList" sys:attach="dataview" class="sys-template"

dataview:data="{{ imagesArray }}"

>

<li>

<h3>{{ Name }}</h3>

<div>{{ Description }}</div>

</li>

</ul>

Posted in: asp.net | Tags: asp.net asp.net 4.0 asp.net ajax ajax instantiation declarative xmlns declarative instantiation javascript live data binding observer pattern

New Features in ASP.NET AJAX 4, Part 3

The DataView Control

The DataView control can bind to any JavaScript object or array, or to any ASP.NET AJAX component.

Providing Data to the DataView Control

Data can be provided to the DataView control in a number of ways. One way is by setting the data property of the DataView control. The following example shows how to set the DataView control’s data property through declarative binding:

<ul sys:attach="dataview" class="sys-template"

dataview:data="{{ imagesArray }}"

>

<li>

<h3>{{ Name }}</h3>

<div>{{ Description }}</div>

</li>

</ul>

The following example shows how to set the DataView control’s data property through code:

<script type="text/javascript">

function pageLoad() {

imagesService.GetImages(querySucceeded);

}

function querySucceeded(result) {

$find("imagesList").set_data(result);

}

</script>

<ul id="imagesList" sys:attach="dataview" class="sys-template">

<li>

<h3>{{ Name }}</h3>

<div>{{ Description }}</div>

</li>

</ul>

Another way to provide data is to specify a WCF or ASP.NET Web service directly in the dataProvider property of the DataView control, as shown in the following example:

<ul sys:attach="dataview" class="sys-template"

dataview:dataprovider="../Services/imagesService.svc"

dataview:fetchOperation="GetImages"

>

<li>

<h3>{{ Name }}</h3>

<div>{{ Description }}</div>

</li>

</ul>

When the DataView control’s dataProvider property is set, the DataView control will use the provider (in this case, the Web service) to fetch data by using the operation specified in the fetchOperation property. For other examples in which the dataProvider property is set to an instance of the DataContext class (used for read-write scenarios) see The DataContext and AdoNetDataContext Classes later in this document.

Additional Features of the DataView Control

The DataView control provides a number of features that are not shown in the previous examples, such as support for layout templates and external templates, built-in selection support for use in master-detail scenarios, command bubbling, and so on. The following example illustrates how to use some of these features to configure linked master-detail views, using two DataView controls that are linked through live binding.

<!--Master View-->

<ul sys:attach="dataview" class=" sys-template"

dataview:dataprovider="../Services/ImageService.svc"

dataview:fetchOperation="GetImages"

dataview:selecteditemclass="myselected"

dataview:sys-key="master"

>

<li sys:command="Select">{{ Name }}</li>

</ul>

<!--Detail View-->

<div class="sys-template"

sys:attach="dataview"

dataview:data="{binding selectedData, source={{master}} }"

>

<div>Name: <input type="text" value="{binding Name}"/></div>

<div>Description: <input type="text" value="{binding Description}"/></div>

</div>

The Select command in the master view template ensures that when the user clicks one of the items rendered by the master view, that item becomes the selected item. As a result, the CSS class specified in the selectedItemClass property of the master DataView control is applied to the markup for that item. In addition, the corresponding data item becomes the value that is returned by the selectedData property of the master DataView control.

The detail DataView control uses live binding so that its data item is dynamically set to the current selectedData value of the master DataView control. In the example, the detail view provides an edit template with two-way binding that lets users modify the fields of the data item.

Posted in: asp.net | Tags: asp.net asp.net 4.0 asp.net ajax ajax dataview providing data

New Features in ASP.NET AJAX 4, part 4

The AdoNetServiceProxy Class

The AdoNetServiceProxy class enables read-write interaction with ADO.NET Data Services from JavaScript. The class enables access from JavaScript to a broad range of features of ADO.NET Data Services. It provides direct programmatic access to the basic REST operations provided by ADO.NET Data Services (insert, query, update, and remove), as well as many advanced features such as verb tunneling (custom HTTP methods) and optimistic concurrency.

The AdoNetServiceProxy class is used by the AdoNetDataContext class in read-write scenarios, as explained in the next section.

The DataContext and AdoNetDataContext Classes

For read-write scenarios that use Web services or data services, ASP.NET AJAX 4 provides a DataContext class that provides full support for change tracking in the browser. This enables complete end-to-end AJAX-based data scenarios.

Typically, data is fetched from the server through JSON services such as a WCF AJAX-enabled service or ADO.NET data services. The data is displayed to the user through dynamic data-driven UI, using the DataView control. Declarative live-binding markup in the template provides users with an edit UI, which enables them to modify the data. The ASP.NET AJAX DataContext class tracks all changes to the data automatically. All changes can then be sent at once to the server by calling the SaveChanges method of the DataContext class. A single DataContext instance can manage change tracking for data returned by different operations on the server, even if the operations return different types of objects.

The following example shows how to use the DataContext class.

<script type="text/javascript">

var dataContext = new Sys.Data.DataContext();

dataContext.set_serviceUri("../Services/imagesService.svc");

dataContext.set_saveOperation("SaveImages");

dataContext.initialize();

</script>

<button onclick="dataContext.saveChanges()" class="right">Save Changes</button>

<ul sys:attach="dataview" class="sys-template"

dataview:dataprovider="{{ dataContext }}"

dataview:query="GetImages"

>

<li>

<input type="text" value="{binding Name}"/><br/>

<input type="text" value="{binding Description}"/>

</li>

</ul>

If you are using an ADO.NET data service, you should use the AdoNetDataContext class instead of the more general-purpose DataContext class. (AdoNetDataContext derives from DataContext.) The AdoNetDataContext class provides additional support for features that are specific to ADO.NET, such as identity management, links and associations between entity sets that are returned in different fetch operations, hierarchical data, and optimistic concurrency.

Refactoring the Microsoft AJAX Framework Libraries

ASP.NET AJAX 4 also introduces the ability to use only parts of the ASP.NET AJAX framework for efficiency, as well as the ability to use the ScriptManager control without using the ASP.NET AJAX framework at all. The ScriptManager control provides services such as centralized management of references, support for debug and release modes, support for localization, and script combining. These services can be useful to all client-script developers, even those who use JavaScript libraries other than Microsoft AJAX, such as jQuery. Until now, the ScriptManager control included the Microsoft ASP.NET AJAX library automatically, without providing a simple way to opt out of it. As a result, when developers used the ScriptManager control in their pages, the effect was to include the whole Microsoft ASP.NET AJAX library in their applications.

In ASP.NET 4, the default behavior for the ScriptManager control is to include the complete ASP.NET AJAX library. However, the ScriptManager control supports a new MicrosoftAjaxMode property that lets you choose a subset of the framework by using only portions of the library in the form of split script files. The MicrosoftAjaxMode property can have one of the following values:

· Enabled — All Microsoft AJAX scripts are included (legacy behavior). This is the default value of the property.

· Explicit — Each split script file must be added explicitly; it is up to you to make sure that you include all scripts that have dependencies on one another.

· Disabled — All Microsoft ASP.NET AJAX script features are disabled and the ScriptManager control does not reference any scripts automatically.

When you use Explicit mode, the scripts that are available are as follows:

· MicrosoftAjaxCore.js

· MicrosoftAjaxComponentModel.js

· MicrosoftAjaxSerialization.js

· MicrosoftAjaxGlobalization.js

· MicrosoftAjaxHistory.js

· MicrosoftAjaxNetwork.js

· MicrosoftAjaxWebServices.js

· MicrosoftAjaxApplicationServices.js

· MicrosoftAjaxTemplates.js (New for ASP.NET AJAX 4)

· MicrosoftAjaxAdoNet.js (New for ASP.NET AJAX 4)

The following chart shows the dependencies between split scripts. The violet boxes that are labeled Templates (AdoNetDataContext) and Templates (DataContext) indicate that only these classes in MicrosoftAjaxTemplates.js have the indicated dependency. Thus, MicrosoftAjaxTemplates.js does not require MicrosoftAjaxWebServices.js unless you use the DataContext class, and it does not require MicrosoftAjaxAdoNet.js unless you use the AdoNetDataContext class.

The WebForms box for the MicrosoftAjaxWebForms.js script is green to indicate that it is included automatically when you set EnablePartialRendering to true (which is the default setting for the ScriptManager control).

As an example, to use the ASP.NET AJAX browser history feature with no partial rendering and with MicrosoftAjaxMode set to Explicit, the ScriptManager control must be configured as in the following example:

<asp:ScriptManager ID="ScriptManager1"

EnablePartialRendering="false"

MicrosoftAjaxMode="Explicit"

EnableHistory="true"

runat="server">

<CompositeScript>

<Scripts>

<asp:ScriptReference Name="MicrosoftAjaxCore.js" />

<asp:ScriptReference Name="MicrosoftAjaxComponentModel.js" />

<asp:ScriptReference Name="MicrosoftAjaxSerialization.js" />

<asp:ScriptReference Name="MicrosoftAjaxHistory.js" />

</Scripts>

</CompositeScript>

</asp:ScriptManager>

In the example, EnablePartialRendering has been set to false so that MicrosoftAjaxWebForms.js is not included automatically, and EnableHistory has been set to true so that the ScriptManager control can use the AJAX browser history feature. Order is important when you include split scripts — if a script has dependencies, the ScriptReference elements for those dependencies must be listed before the ScriptReference element for the script itself.

Note that split script files should be used only by developers who are concerned about optimizing for very high performance. When split script files are used, they should be used together with script combining to minimize the numbers of requests that are required in order to download the scripts.

The DOM Ready Event

In Beta 2, changes in ASP.NET make it easier to use Microsoft AJAX when you create an ASP.NET MVC application or pure client Web application. In versions earlier than Beta 2, if you wanted to use the pageLoad method outside a Web Forms application, for performance reasons you needed to call sys.application.initialize at the bottom of the page. Otherwise, the pageLoad method would not be called until the window.onload event was raised.

In Beta 2, the pageLoad method is called immediately after the document DOM content is finished loading and before the window.onload event. You no longer need to call sys.application.initialize to cause the pageLoad method to be called before window.onload occurs.

Using JSONP to Retrieve Cross-Domain Data

Ordinarily, when you make an AJAX request from a page, you are limited to making a request to the domain that hosts the page. In other words, you are not allowed to make cross-domain requests.

In Beta 2, ASP.NET AJAX includes support for JSONP. Using JSONP, you can interact with services that are located in another domain.

No special configuration is required in order to take advantage of JSONP when you create a service reference. You simply configure the service path of the service to include a reference to the target domain, as shown in the following example:

<asp:ScriptManager ID="ScriptManager1" runat="server">

<Services>

<asp:ServiceReference Path="http://AnotherDomain/Books.svc" />

</Services>

</asp:ScriptManager>

In order to use JSONP to make cross-domain requests, you must interact with a JSONP-enabled service. For example, if you want to request data from a WCF service, the service must be enabled to support JSONP. For more information about how to enable JSONP for a WCF service, see the article JSON with Padding (AJAX) on the MSDN Web site.

Posted in: | Tags: asp.net asp.net 4.0 asp.net ajax ajax adonetdatacontext datacontext adonetserviceproxy ajax framework json jquery microsoftajaxglobalization microsoftajaxhistory microsoftajaxapplicationservices microsoftajaxadonet

ASP.NET Chart Control 4.0

The ASP.NET Chart control expands the data-visualization offerings in the .NET Framework. Using the Chart control, you can easily create ASP.NET pages that have intuitive and visually compelling charts for complex statistical or financial analysis. The ASP.NET Chart control was introduced as an add-on to the .NET Framework version 3.5 SP1 release and will become part of the .NET Framework 4 release.

Major features of the control include the following:

· 35 distinct chart types.

· An unlimited number of chart areas, titles, legends, and annotations.

· A wide variety of appearance settings for all chart elements.

· 3-D support for most chart types.

· Smart data labels that can automatically fit around data points.

· Strip lines, scale breaks, and logarithmic scaling.

· More than 50 financial and statistical formulas for data analysis and transformation.

· Simple binding and manipulation of chart data.

· Support for common data formats, such as dates, times, and currency.

· Support for interactivity and event-driven customization, including client click events using AJAX.

· State management.

· Binary streaming.

The following figures show examples of financial charts that are produced by the ASP.NET Chart control.

For more examples of how to use the ASP.NET Chart control, download the sample code on the Samples Environment for Microsoft Chart Controls page on the MSDN Web site. You can find more samples of community content at the Chart Control Forum.

Adding the Chart Control to an ASP.NET Page

The following example shows how to add a Chart control to an ASP.NET page by using markup. In the example, the Chart control produces a column chart for static data points.

<asp:Chart ID="Chart1" runat="server">

<Series>

<asp:Series Name="Series1" ChartType="Column">

<Points>

<asp:DataPoint AxisLabel="Product A" YValues="345"/>

<asp:DataPoint AxisLabel="Product B" YValues="456"/>

<asp:DataPoint AxisLabel="Product C" YValues="125"/>

<asp:DataPoint AxisLabel="Product D" YValues="957"/>

</Points>

</asp:Series>

</Series>

<ChartAreas>

<asp:ChartArea Name="ChartArea1">

<AxisY IsLogarithmic="True" />

</asp:ChartArea>

</ChartAreas>

<Legends>

<asp:Legend Name="Legend1" Title="Product Sales" />

</Legends>

</asp:Chart>

Using 3-D Charts

The Chart control contains a ChartAreas collection, which can contain ChartArea objects that define characteristics of chart areas. For example, to use 3-D for a chart area, use the Area3DStyle property as in the following example:

<asp:ChartArea Name="ChartArea1">

<area3dstyle

Rotation="10"

Perspective="10"

Enable3D="True"

Inclination="15"

IsRightAngleAxes="False"

WallWidth="0"

IsClustered="False" />

<%-- Additional markup here --%>

</asp:ChartArea>

The figure below shows a 3-D chart with four series of the Bar chart type.

Using Scale Breaks and Logarithmic Scales

Scale breaks and logarithmic scales are two additional ways to add sophistication to the chart. These features are specific to each axis in a chart area. For example, to use these features on the primary Y axis of a chart area, use the AxisY.IsLogarithmic and ScaleBreakStyle properties in a ChartArea object. The following snippet shows how to use scale breaks on the primary Y axis.

<asp:ChartArea Name="ChartArea1">

<axisy>

<ScaleBreakStyle

BreakLineStyle="Wave"

CollapsibleSpaceThreshold="40"

Enabled="True" />

</axisy>

<%-- Additional markup here --%>

</asp:ChartArea>

The figure below shows the Y axis with scale breaks enabled.

Posted in: asp.net | Tags: asp.net asp.net 4.0 chart chart control asp.net chart chartarea scalebreakstyle breaklinestyle axisy collapsiblespacethreshold isrightangleaxes wallwidth

Filtering Data with the QueryExtender Control

A very common task for developers who create data-driven Web pages is to filter data. This traditionally has been performed by building Where clauses in data source controls. This approach can be complicated, and in some cases the Where syntax does not let you take advantage of the full functionality of the underlying database.

To make filtering easier, a new QueryExtender control has been added in ASP.NET 4. This control can be added to EntityDataSource or LinqDataSource controls in order to filter the data returned by these controls. Because the QueryExtender control relies on LINQ, the filter is applied on the database server before the data is sent to the page, which results in very efficient operations.

The QueryExtender control supports a variety of filter options. The following sections describe these options and provide examples of how to use them.

Search

For the search option, the QueryExtender control uses provided text to find records in specified fields. In the following example, the control uses the text that is entered in the TextBoxSearch control and searches for its contents in the ProductName and Supplier.CompanyName columns in the data returned from the LinqDataSource control.

<asp:LinqDataSource ID="dataSource" runat="server"> TableName="Products">

</asp:LinqDataSource>

<asp:QueryExtender TargetControlID="dataSource" runat="server">

<asp:SearchExpression DataFields="ProductName, Supplier.CompanyName"

SearchType="StartsWith">

<asp:ControlParameter ControlID="TextBoxSearch" />

</asp:SearchExpression>

</asp:QueryExtender>

Range

The range option is similar to the search option, but specifies a pair of values to define the range. In the following example, the QueryExtender control searches the UnitPrice column in the data returned from the LinqDataSource control. The range is read from the TextBoxFrom and TextBoxTo controls on the page.

<asp:LinqDataSource ID="dataSource" runat="server"> TableName="Products">

</asp:LinqDataSource>

<asp:QueryExtender TargetControlID="dataSource" runat="server">

<asp:RangeExpression DataField="UnitPrice" MinType="Inclusive"

MaxType="Inclusive">

<asp:ControlParameter ControlID="TextBoxFrom" />

<asp:ControlParameter ControlID="TexBoxTo" />

</asp:RangeExpression>

</asp:QueryExtender>

PropertyExpression

The property expression option lets you define a comparison to a property value. If the expression evaluates to true, the data that is being examined is returned. In the following example, the QueryExtender control filters data by comparing the data in the Discontinued column to the value from the CheckBoxDiscontinued control on the page.

<asp:LinqDataSource ID="dataSource" runat="server" TableName="Products">

</asp:LinqDataSource>

<asp:QueryExtender TargetControlID="dataSource" runat="server">

<asp:PropertyExpression>

<asp:ControlParameter ControlID="CheckBoxDiscontinued" Name="Discontinued" />

</asp:PropertyExpression>

</asp:QueryExtender>

CustomExpression

Finally, you can specify a custom expression to use with the QueryExtender control. This option lets you call a function in the page that defines custom filter logic. The following example shows how to declaratively specify a custom expression in the QueryExtender control.

<asp:LinqDataSource ID="dataSource" runat="server" TableName="Products">

</asp:LinqDataSource>

<asp:QueryExtender TargetControlID="dataSource" runat="server">

<asp:CustomExpression OnQuerying="FilterProducts" />

</asp:QueryExtender>

The following example shows the custom function that is invoked by the QueryExtender control. In this case, instead of using a database query that includes a Where clause, the code uses a LINQ query to filter the data.

protected void FilterProducts(object sender, CustomExpressionEventArgs e)

{

e.Query = from p in e.Query.Cast<Product>()

where p.UnitPrice >= 10

select p;

}

These examples show only one expression being used in the QueryExtender control at a time. However, you can include multiple expressions inside the QueryExtender control.

Posted in: asp.net | Tags: asp.net asp.net 4.0 queryextender queryextender queryextender control filtering filter linqdatasource targetcontrolid searchexpression searchtype propertyexpression linq