Scott Hanselman

C# 4 and the dynamic keyword - Whirlwind Tour around .NET 4 (and Visual Studio 2010) Beta 1

May 20, '09 Comments [15] Posted in DLR | Learning .NET | TechEd
Sponsored By

I've posted twice so far on .NET 4, first on ASP.NET 4, then on improvements in C# around dynamism and PIAs as well as the COM Binder. Now "dynamic."

So I asked this guy, what's up with the dynamic keyword, and what type was it exactly? I mean, C# isn't dynamic, right? He says:

"Oh, well it's statically-typed as a dynamic type."

Then my brain exploded and began to leak out my ears. Honestly, though, it took a second. Here's a good example from some of Ander's slides:

Calculator calc = GetCalculator();
int sum = calc.Add(10, 20);

That's the creation of an object, invokation of a method, and the collection of a return value. This is the exact same code, as the "var" type is figured out at compile time.

var calc = GetCalculator();
int sum = calc.Add(10, 20);

If you wanted to do the exact same thing, except with Reflection (like if it were some other class, maybe old-COM interop, or something where the compiler didn't know a priori that Add() was available, etc) you'd do this:

object calc = GetCalculator();
Type calcType = calc.GetType();
object res = calcType.InvokeMember("Add",
BindingFlags.InvokeMethod, null,
new object[] { 10, 20 });
int sum = Convert.ToInt32(res);

It's pretty horrible to look at, of course. If the object is some dynamic thing (from any number of sources), we can do this:

dynamic calc = GetCalculator();
int sum = calc.Add(10, 20);

And get the dynamic method invocation and conversion of the return type. Basically it looks just like we're calling any other object.

Dynamism?

Here's the differences you see while coding. Hovering over the keyword gives me this nice tooltip.

image

When I hit the "." expecting intellisense to save me from my ignorance:

image 

I'm told this is a dynamic expression that will be resolved at runtime.

Here's a C# program calling a method in a python (.py) file:

ScriptRuntime py = Python.CreateRuntime();
dynamic random = py.UseFile("random.py");

//Make an array of numbers
var items = Enumerable.Range(1, 7).ToArray();

random.shuffle(items);

Here we're passing in an array if ints (System.Int32[]) into the Python 'shuffle' method and it works just fine.

image

The DLR basically enables everyone to talk to everyone. That includes not just Python and Ruby, but Silverlight, Office/COM, and others.

What price REPL?

John Lam has a great post about his TechEd talk where he took a spin on a traditional REPL (READ-EVAL-PRINT-LOOP) using the DLR. He even allows switching back and forth between languages, which is odd/interesting.

John's even put the code for his REPL up on GitHub. Why is this interesting? Well...

Screenshot of John Lam's REPL/editor

He took his REPL and embedded it into an example Open Source app, specifically Witty, a WPF Twitter Client. Why he didn't use BabySmash is beyond me. ;) Check it out, as well as the source code diff for Witty on John's blog.

It'll be nice to have this kind of dynamic stuff just baked in and waiting for me to use it.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

The Weekly Source Code 42 - Tree Trim, Plugins, and MEF

May 20, '09 Comments [5] Posted in Open Source | Source Code
Sponsored By

image I really advocate folks reading as much source as they can because you become a better writer by reading as much as writing. That's the whole point of the Weekly Source Code - reading code to be a better developer.

Reading code in Open Source projects is a good way to learn, especially if the project has been around a while and been successful, or if you already respect the team of people working on it. Less reliably, you can find snippets of code by searching and sharing code.

Tree Trim == CleanSources++

Many years ago, Omar Shahine wrote a great little app called Clean Sources. It added a right-click menu to the Windows Explorer that would delete your bin, obj and setup folders.

Later, Jeff wrote Clean Sources Plus. It added a "Clean and Zip" option as well as support for removing source control bindings.

Now, Steve Dunn has extended these to create Tree Trim, a command-line tool to do all this and more. He's extended it to include a plugin model that creates a little pipeline of plugins. You can chain them together and extend the command-line with your own plugins, and MEF (Managed Extensibility Framework) is at its core.

Tree Trim is convenient for build servers where you want to, for example, make a working copy, delete source control bindings, zip stuff up, email it, etc.

Each command line argument is a "task" and each command line arg (moniker) maps to a object.

treetrim.console.exe c:\dev\myproject -workingCopy -deleteFromDisk -zip -email

It's significant that order of arguments matter, so the args cause the plugins to run in order, like "make working copy, delete bin/obj, zip up, email."

Make your own Plugin and be MEFy

He's got an IPlugin interface:

public interface IPlugin
{
string Moniker { get ; }
string WorkingPath { get ; }
void Cleanup( ) ;
void Run(IPluginRuntimeSettings settings, IPlugin lastPlugin);
}

When you make a plugin, you need to let MEF know that it's available by Exporting the type:

[Export(typeof(IPlugin))]
public class SomePlugin : IPlugin
{
...
public string Moniker
{
get { return @"newPluginArgument" ; }
}
...
}

Then any plugin in the same directory gets pulled into a list of plugins...

public DiscoverPluginsInAssemblyDirectory( )
{

var catalog = new DirectoryCatalog(disk.DirectoryOfExecutingAssembly);

var container = new CompositionContainer(catalog);

var batch = new CompositionBatch();
batch.AddPart(this);

container.Compose(batch);
}

[Import( typeof( IPlugin ) )]
public IList<IPlugin> Plugins
{
get;
set;
}

The app kicks off this little pipeline by passing the command line args in along with the plugins found:

Trimmer.TrimTree(
new TaskCollection( pluginDiscoverer.DiscoveredPlugins, commandLineArgs ),
path );

...then...

public static void TrimTree(ITaskCollection tasks, string sourceTreeRoot)
{
ITask lastTask = new Task { Plugin = new NullPlugin( sourceTreeRoot ) } ;

foreach ( ITask eachTask in tasks )
{
eachTask.Run( lastTask );

lastTask = eachTask ;
}

IEnumerable<ITask> reversedTasks = tasks.Reverse( ) ;

foreach (ITask eachTask in reversedTasks)
{
eachTask.Cleanup();
}
}

The code is actually very easy to read and is up at TreeTrim on Google Code and check out the FAQ. Plugins are super easy with MEF and Tree Trim has some good examples of a number of things. First, just plugins in general, but also a technique for passing settings to plugins.

Add Context Menus to Explorer

You can easily create context menus in Explorer for this tool (or any tool). Add a Key to the Registry like below.

HKEY_CLASSES_ROOT\Folder\shell\<WHATEVER TEXT YOU WANT>\command

Then in the (Default) string value, put it something like this (for example):

"C:\Program Files (x86)\Tree Trim\TreeTrim.Gui.exe" "%1"  -workingcopy -deletefromdisk -zip:writeTo:"c:\users\scott\desktop\justzipped.zip"+dontCleanUp

Here's how it looks in registry:

Registry Editor (2)

Steve is also starting to setup tests using XUnit. He's starting to use the ContextSpecification Pattern for his tests, so it'll be interesting to see if he completes the tests. That part is pretty basic so far. Check out the TaskCollectionSpecs.cs as an example.

All in all, fun to read, and an interesting tool I'll use to quickly clean and send code samples around. I may extend it with a plugin to upload to my blog, then put the link in the clipboard. That could make blogging samples easier.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

CLR and DLR and BCL, oh my! - Whirlwind Tour around .NET 4 (and Visual Studio 2010) Beta 1

May 20, '09 Comments [18] Posted in BCL | Learning .NET | TechEd
Sponsored By

Just got a great tweet from Jeremiah Morrill about .NET 4.

"Office and COM Interop that is actually fun to do" Show me! Until then, I'm calling shenanigans.

I love a challenge! In my first Whirlwind Tour post on ASP I mentioned how COM Interop and Office Interop was fun with 4.

I've done a lot of COM Interop with C# and a LOT of Office Automation. Once upon a time, I worked at a company called Chrome Data, and we created a Fax Server with a Digiboard. Folks would call into a number, and the person who took the order would pick the make/model/style/year of the car and "instantly" fax a complete report about the vehicle. It used VB3, SQL Server 4.21 and Word 6.0 and a magical thing called "OLE Automation."

Fast forward 15 years and I sent an email to Mads Torgerson, a PM on C# that said:

I’m doing a sample for a friend where I’m simply spinning through an Automation API over a Word Doc to get and change some CustomDocumentProperties.

I’m really surprised at how current C# sucks at this. Of course, it makes sense, given all the IDispatch code in Word, but still. Dim != var as they say. Fix it!

Well, everything except "fix it!" is true. I added that just now. ;) I did a post on this a while back showing how scary the C# code was. This is/was somewhere where Visual Basic truly excels. I vowed to only use VB for Office Automation code after this fiasco.

If you want to melt your brain, check out the old code. No joke. I've collapsed the block because it's too scary. See the "ref missings"? The reflection? The Get/Sets? Scandalous!

{
ApplicationClass WordApp = new ApplicationClass();
WordApp.Visible = true;
object missing = System.Reflection.Missing.Value;
object readOnly = false;
object isVisible = true;
object fileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\..\..\NewTest.doc");
Microsoft.Office.Interop.Word.Document aDoc = WordApp.Documents.Open(
ref fileName,ref missing,ref readOnly,ref missing,
ref missing,ref missing,ref missing,ref missing,
ref missing,ref missing,ref missing,ref isVisible,
ref missing,ref missing,ref missing,ref missing);

aDoc.Activate();

string propertyValue = GetCustomPropertyValue(aDoc, "CustomProperty1");
SetCustomPropertyValue(aDoc, "CustomProperty1", "Hanselman");

foreach (Range r in aDoc.StoryRanges)
{
r.Fields.Update();
}
}

public string GetCustomPropertyValue(Document doc, string propertyName)
{
object oDocCustomProps = doc.CustomDocumentProperties;
Type typeDocCustomProps = oDocCustomProps.GetType();
object oCustomProp = typeDocCustomProps.InvokeMember("Item",
BindingFlags.Default |
BindingFlags.GetProperty,
null, oDocCustomProps,
new object[] { propertyName });

Type typePropertyValue = oCustomProp.GetType();
string propertyValue = typePropertyValue.InvokeMember("Value",
BindingFlags.Default |
BindingFlags.GetProperty,
null, oCustomProp,
new object[] { }).ToString();

return propertyValue;
}

public void SetCustomPropertyValue(Document doc, string propertyName, string propertyValue)
{
object oDocCustomProps = doc.CustomDocumentProperties;
Type typeDocCustomProps = oDocCustomProps.GetType();
typeDocCustomProps.InvokeMember("Item",
BindingFlags.Default |
BindingFlags.SetProperty,
null, oDocCustomProps,
new object[] { propertyName, propertyValue });
}

Fast forward to C# under .NET 4.

var WordApp = new ApplicationClass();
WordApp.Visible = true;
string fileName = @"NewTest.doc";
Document aDoc = WordApp.Documents.Open(fileName, ReadOnly: true, Visible: true);
aDoc.Activate();

string propertyValue = aDoc.CustomDocumentProperties["FISHORTNAME"].Value;
aDoc.CustomDocumentProperties["FISHORTNAME"].Value = "HanselBank";
string newPropertyValue = aDoc.CustomDocumentProperties["FISHORTNAME"].Value

foreach (Range r in aDoc.StoryRanges)
{
foreach (Field b in r.Fields)
{
b.Update();
}
}

See how all the crap that was originally reflection gets dispatched dynamically? But that's not even that great an example.

Word and Excel Automation with C# 4

That's just an example from Jonathan Carter and Jason Olson that gets running processes (using LINQ, woot) then makes a chart in Excel, then puts the chart in Word.

using System;
using System.Diagnostics;
using System.Linq;
using Excel = Microsoft.Office.Interop.Excel;
using Word = Microsoft.Office.Interop.Word;

namespace One.SimplifyingYourCodeWithCSharp
{
class Program
{
static void Main(string[] args)
{
GenerateChart(copyToWord: true);
}

static void GenerateChart(bool copyToWord = false)
{
var excel = new Excel.Application();
excel.Visible = true;
excel.Workbooks.Add();

excel.get_Range("A1").Value2 = "Process Name";
excel.get_Range("B1").Value2 = "Memory Usage";

var processes = Process.GetProcesses()
.OrderByDescending(p => p.WorkingSet64)
.Take(10);
int i = 2;
foreach (var p in processes)
{
excel.get_Range("A" + i).Value2 = p.ProcessName;
excel.get_Range("B" + i).Value2 = p.WorkingSet64;
i++;
}

Excel.Range range = excel.get_Range("A1");
Excel.Chart chart = (Excel.Chart)excel.ActiveWorkbook.Charts.Add(
After: excel.ActiveSheet);

chart.ChartWizard(Source: range.CurrentRegion,
Title: "Memory Usage in " + Environment.MachineName);

chart.ChartStyle = 45;
chart.CopyPicture(Excel.XlPictureAppearance.xlScreen,
Excel.XlCopyPictureFormat.xlBitmap,
Excel.XlPictureAppearance.xlScreen);

if (copyToWord)
{
var word = new Word.Application();
word.Visible = true;
word.Documents.Add();

word.Selection.Paste();
}
}
}
}

Notice the named parameters in C#, like 'Title: "whatever"' and "copyToWord: true"?

PIAs no long stand for Pain in the *ss - Type Equivalence and Embedded Interop Assemblies

Primary Interop Assemblies are .NET assemblies that bridge the gap between a .NET app and a COM server. They are also a PIA, ahem. When there's articles about your technology on the web called "Common Pitfalls With ______" you know there's trouble.

Typically you reference these Interop assemblies in Visual Studio and they show up, predictably, as references in your assembly. Here's a screenshot with the project on the right, and the assembly under Reflector on the left.

image

This means that those PIAs better be deployed on the end user's machine. Some PIAs can be as large as 20 megs or more! That's because for each COM interface, struct, enum, etc, there is a managed equivalent for marshalling data. That sucks, especially if I just want to make a chart and I'm not using any other types. It's great that Office has thousands of types, but don't make me carry them all around.

However, now I can click on Properties for these references and click Embed Interop Types = true. Now, check the screenshot. The references are gone and new types have appeared.

 image

Just the types I was using are now embedded within my application. However, since the types are equivalent, the runtime handles this fact and we don't have to do anything.

This all adds up to Office and COM Interop that is actually fun to do. Ok, maybe not fun, but better than a really bad paper cut. Huh, Jeremiah? ;)

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

ASP 4 - Whirlwind Tour around .NET 4 (and Visual Studio 2010) Beta 1

May 19, '09 Comments [14] Posted in ASP.NET | ASP.NET Dynamic Data | ASP.NET MVC | TechEd
Sponsored By

Hey, we released Visual Studio 2010 Beta 1. JasonZ has a great post with piles of details and a metric crapload of screenshots. Definitely take a moment (or eight) and check out his very detailed post. You can get it NOW if you're an MSDN Subscriber, or after the general announcement on Weds if you're not.

UPDATE: My bad, of course it's called ASP.NET 4 and not ASP 4. Sorry, typo.

Should You Freak Out?

I don't think so. There's a lot of stuff that's new and added in .NET 4, but not in that "overwhelming-I-need-to-relearn-everything" way. More in that, "oh, this is way easier/simpler now" way. Like, moving data around with ADO.NET DataServices is easy, binding with client templates is easy, there's F# if you need it, the "dynamic" keyword if you need it, Silverlight's already installed, oh, and the parallel stuff will freak you out, but in a good way.

I'll do a series of posts on what I think is cool with lots of details. I'll put code samples up also as I can. I will also point out where you can already do much of this with 3.5 SP1, as well.

Here's a general outline of a small part of the goodness:

  • New Shell, new File|New, new Extensions Manager
  • Lots of focus on "Code First" (TDD-friendly, etc)
  • Office and COM Interop that is actually fun to do.
  • Automatic Properties for VB, no more "_" for multi-line, inline subs, collection initializers
  • C# gets the dynamic keyword
  • F# is included out of the box
  • WPF Databinding in the Designer
  • Silverlight included out of the box
  • Piles of HTML Snippets for non-designer people
  • Better JavaScript Intellisense
  • MSBuild for C++
  • UML for VS Team Architecture
  • TFS Branch and Changeset visualizers
  • Parallel computing
  • Workflow speedup, new designer
  • SharePoint tooling

Rather than try to top Jason with a laundry list of what's new and what not, here's some details on a few things that I find particularly interesting. They may be obscure to you, and perhaps not deeply interesting, but they were interesting enough to me that I used them for demos at TechEd last week (with a hat tip to Jonathan Carter and Jason Olson).

This is just a smattering of the features (hence: "Whirlwind" although "totally random cool stuff" would have also worked) coming in .NET 4. These are features I'm interested in because they've solved problems I've had in the past.

I'm realizing I'll definitely do these as separate posts because they're going to get long. First, ASP.NET and Ajax.

ASP.NET 4

There is an excellent whitepaper at http://www.asp.net/learn/whitepapers/aspnet40/ with a lot of detail on the changes in ASP.NET 4.

There's lots new in ASP.NET 4, but at TechEd09 I showed two. First was control over my controls' client ids. Rather than getting a generated ID like ctl09_list45_whatever99, I can make my control ids more predictable.

More Control over ClientIDs in WebForms

For example, here's a ListView (ol/li) of Television shows. It uses jQuery to be sortable. Notice the new attributes in asp:ListView, specifically ClientIDRowSuffix and ClientIDMode.

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Television Series Picker</title>
<link href="Default.css" rel="stylesheet" type="text/css" />
<script src="jquery-1.3.2.min.js" type="text/javascript"></script>
<script src="ui.core.js" type="text/javascript"></script>
<script src="ui.sortable.js" type="text/javascript"></script>
<script type="text/javascript">

$(document).ready(function() {
$("#televisionList li").append("<div><span>Click</span></div>");
$("#televisionList").sortable({ handle: $("#televisionList li div") });
});
</script>
</head>
<body>
<form runat="server">
<h1>Television Series Picker</h1>
<p>Order the following television series' based on which you think is most awesome:</p>
<asp:ListView
DataSourceID="televisionDataSource"
ClientIDRowSuffix="ID"
ClientIDMode="Predictable"
runat="server">
<LayoutTemplate>
<ol id="televisionList">
<asp:PlaceHolder ID="itemPlaceHolder" runat="server" />
</ol>
</LayoutTemplate>
<ItemTemplate>
<li id="televisionItem" runat="server">
<%# Eval("Name") %>
</li>
</ItemTemplate>
</asp:ListView>
<asp:ObjectDataSource
ID="televisionDataSource"
TypeName="_01_ClientId.TelevisionDataProvider"
SelectMethod="GetTelevisionSeries"
runat="server" />
</form>
</body>
</html>

The list is populated using an ObjectDataSource and I want the client id's to be created with a suffix using the ID property from the Television object.

Routing and WebForms

You probably know that System.Web.Routing is a big part of ASP.NET MVC, and you may know it's in .NET 3.5 SP1 as well. In .NET 4 it'll be even more easy to use with better support for WebForms. For example:

public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.Add("Product",
new Route("Products/{category}",
new PageRouteHandler("~/Products.aspx")));
}
}

Here I'm setting update a route such that /Products/SomeCategory routes to the /Products.aspx WebForms Page. The Category parameter is a RouteParameter and can be retrieved (of course) and used. System.Web.UI.Page has a RouteData parameter now, or you can refer to RouteValues in your ASPX markup. For example:

<p>The following are all the products within this category:</p>
<h2><asp:Literal Text="<%$ RouteValue:Category %>" runat="server" /></h2>

or into a Data Source via <RouteParameter>:

<asp:EntityDataSource
ID="productsDataSource"
ContextTypeName="AdventureWorksLTEntities"
EntitySetName="Products"
OrderBy="it.Name"
Where="it.Category.Name = @Category"
runat="server">
<WhereParameters>
<asp:RouteParameter
Name="Category"
RouteKey="Category"
Type="String" />
</WhereParameters>
</asp:EntityDataSource>

There will also be Routing Extension Methods like GetUrlForRoute or the like, in Beta 2, as well as IgnoreRoute. Basically anything that makes it simple, simple, simple to use Routes with WebForms. This'll be nice for hybrid WebForms/MVC apps as well.

Ajax 4

The Client Templates stuff in Ajax 4 is pretty sweet. This allows for 2-way data-binding using only JavaScript. For example, this template pulls from a JSON DataService at customers.svc. The JavaScript is below. We create a DataContext pointing to that endpoint, two DataViews that take the "customers-template" and "customer-template" HTML elements and creates a binding between them.

Sys.Application.add_init(function()
{
var dataContext = $create(Sys.Data.AdoNetDataContext,
{
serviceUri: "Customers.svc"
});

var customersTemplate = $create(Sys.UI.DataView,
{
dataProvider: dataContext,
fetchOperation: "Customers",
fetchParameters: { $top: 20, $orderby: "FirstName", $expand: "Orders" },
initialSelectedIndex: 0,
selectedItemClass: "selected"
},
null, null,
$get("customers-template"));

var customerTemplate = $create(Sys.UI.DataView,
null, null, null,
$get("customer-template"));

// This imperatively creates the binding
// between the customer grid and the customer
// detail form. When you select a record in
// the grid, it will automatically re-bind
// the detail view as well.
$create(Sys.Binding,
{
defaultValue: null,
source: customersTemplate,
path: "selectedData",
target: customerTemplate,
targetProperty: "data"
});

// This uses jQuery live event bindings to hook up
// the click event for the update button that will be
// "generated" when the customer detail form is bound.
$("#update-button").live("click", function()
{
dataContext.saveChanges();
});
});

Then we use jQuery live events, and then save the changes back to the dataContext. The changes that are made on the client side are tracked automatically, and those changes are sent back via JSON and commited. Note the source: and target: in the $create() call above that sets the master/detail relationship between customers and customer (singular.)

The client-side templates are similar to the server-side templates you probably already know how to use. You can even use expressions like to conditionally apply CSS.

image

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>AdventureWorks AJAX</title>
<link href="Content/Styles/reset-min.css" rel="stylesheet" type="text/css" />
<link href="Content/Styles/Default.css" rel="stylesheet" type="text/css" />

<script src="Content/Scripts/MicrosoftAjax.debug.js" type="text/javascript"></script>
<script src="Content/Scripts/MicrosoftAjaxTemplates.debug.js" type="text/javascript"></script>
<script src="Content/Scripts/MicrosoftAjaxAdoNet.debug.js" type="text/javascript"></script>
<script src="Content/Scripts/jquery-1.3.2.min.js" type="text/javascript"></script>

<script src="Content/Scripts/Default.js" type="text/javascript"></script>
</head>
<body
xmlns:sys="javascript:Sys"
xmlns:class="http://schemas.microsoft.com/aspnet/class">
<h1>Customer Directory</h1>
<table cellspacing="0">
<thead>
<tr>
<th>Title</th>
<th>First Name</th>
<th>Middle Name</th>
<th>Last Name</th>
<th>Suffix</th>
</tr>
</thead>
<tbody id="customers-template" class="sys-template">
<tr sys:command="select" class:odd="{{ $index % 2 != 0 }}">
<td>{binding Title, defaultValue=}</td>
<td>{binding FirstName}</td>
<td>{binding MiddleName, defaultValue=}</td>
<td>{binding LastName}</td>
<td>{binding Suffix, defaultValue=}</td>
</tr>
</tbody>
</table>
<fieldset id="customer-template" class="sys-template">
<legend>{{ FirstName + " " + LastName }}</legend>
<label for="first-name">
<span>First Name:</span>
<input type="text" id="first-name" value="{binding FirstName}" />
</label>
<label for="middle-name">
<span>Middle Name:</span>
<input type="text" id="middle-name" value="{binding MiddleName, defaultValue=}" />
</label>
<label for="last-name">
<span>Last Name:</span>
<input type="text" id="last-name" value="{binding LastName}" />
</label>
<input id="update-button" type="button" value="Update" />
</fieldset>
</body>
</html>

This exact scenario can also be done declaratively with you having to write ANY JavaScript at all. The "declarations" from the JavaScript file above are replaced with declarative namespace statements like:

<fieldset
class="sys-template"
sys:attach="dataview"
dataview:data="{binding selectedData, source={{customersTemplate}}}"
dataview:sys-key="customerTemplate">
<legend>{{ FirstName + " " + LastName }}</legend>
...

And the result is the same as above:

image

It's important to point out that while you can go get the VS 2010 Beta 1, you can also play with this stuff TODAY running on .NET 3.5 SP1. Go over to the ASP.NET 4 Ajax Preview site on CodePlex.

Also, don't freak out that ASP.NET MVC isn't baked into VS2010 Beta 1. Phil explains here.

Related Links

Have fun!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Hanselminutes Podcast 162 - PowerShell 2.0

May 19, '09 Comments [0] Posted in Podcast | PowerShell | TechEd
Sponsored By

Windows_PowerShell_iconMy one-hundred-and-sixty-second podcast is up. Scott's at TechEd and bumps into Hal Rottenberg and Kirk Munro. Hal's a PowerShell IT guy and Kirk's a Powershell-focused Dev. What's new in PowerShell 2.0 and what's in it for the .NET developer or Windows power user?

Subscribe: Subscribe to Hanselminutes Subscribe to my Podcast in iTunes

Do also remember the complete archives are always up and they have PDF Transcripts, a little known feature that show up a few weeks after each show.

Telerik is a sponsor for this show!

Building quality software is never easy. It requires skills and imagination. We cannot promise to improve your skills, but when it comes to User Interface, we can provide the building blocks to take your application a step closer to your imagination. Explore the leading UI suites for ASP.NET and Windows Forms. Enjoy the versatility of our new-generation Reporting Tool. Dive into our online community. Visit www.telerik.com.

As I've said before this show comes to you with the audio expertise and stewardship of Carl Franklin. The name comes from Travis Illig, but the goal of the show is simple. Avoid wasting the listener's time. (and make the commute less boring)

Enjoy. Who knows what'll happen in the next show?

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.