Previous month:
July 2010
Next month:
September 2010

August 2010

.NET User Group Austria: MEF mit Christoph Wille

Das nächste Treffen der .NET User Group Austria findet am Mittwoch, 8. September 2010 statt!

Einladung zur .NET User Group Austria
Mittwoch, 8. September 2010
.NET User Group Austria
Location:
it-Versity
Schottenfeldgasse 69, 1070 Wien

Bitte um Anmeldung: ug@christiannagel.com
17:30 Zusammenkunft und Diskussionen
18:00 Präsentation von Christoph Wille, Managed Extensibility Framework

Managed Extensibilty Framework
Das Managed Extensibility Framework (MEF) ist ein wesentlicher Bestandteil von .NET Framework 4.0, und es wird auch für Extensibility in Visual Studio 2010 eingesetzt. In diesem Vortrag erhalten sie einen Überblick über MEF, wie man es in die eigene Anwendung integriert und damit dynamisch die Funktionalität der Applikation beeinflußt.

Christoph Wille ist selbständiger Consultant für Softwareentwicklung, - Architektur und Projektmanagement. Er ist seit den Anfängen bei .NET mit dabei, und hat das welterste Buch zu C# - Presenting C# - geschrieben. Seit der Vorstellung von .NET im Jahr 2000 ist er als Projektleiter bei der Open Source IDE SharpDevelop engagiert, die vollständig in .NET Sprachen implementiert ist und mehr als 5 Millionen Mal downgeloadet wurde. Seinen Einstieg in .NET hat Christoph über ASP.NET gemacht, und er ist aktuell MVP für ASP.NET (davor für “klassisches” ASP).

Danke an die Sponsoren
CN innovation
it-versity


BASTA!

Auch bei der BASTA! in Mainz? Würde mich freuen dich dort zu treffen!

basta10_speaker_en

Von mir gibt es diesmal 3 Sessions:

thinktecture ist ganz groß vertreten. Hier eine Timetable von allen thinktecture-Sessions:

 

Montag 9:30 Oliver Sturm Power Workshop – Tag der .NET Sprachen
Dienstag 9:30 Christian Nagel C# 4 – Was ist neu?
  11:15 Jörg Neumann Entwicklung modulerer Anwendungen mit MEF
  11:15 Oliver Sturm Dynamisch konsumieren in C# 4.0
  14:00 Jörg Neumann Controls für WPF und Silverlight entwickeln
  14:00 Oliver Sturm Dynamsiches C# 4.0 – die “Provider” Seite
  15:30 Christian Nagel Advanced Data Binding mit WPF
  15:30 Dominick Baier Windows Azure und die Cloud – Sicherheiten und Risiken
  15:30 Ingo Rammer Advanced Debugging mit Visual Studio 2008 und 2010
  17:15 Christian Weyer Scharfer Apfel: iPhone in Action mit C#
  19:45 Oliver Sturm Mehrsprachigkeit und die Konsequenzen
Mittwoch 8:30 Dominick Baier Einführung in die Windows Identity Foundation
  10:15 Christian Nagel Was steckt hinter LINQ?
  10:15 Dominick Baier Claims-basierte Anwendungen in der Praxis
  14:00 Richard Blewett LINQ and the Reactive Framework – a powerful new Way to write Code
  17:15 Dominick Baier Sicherheit zum Anfassen und Mitmachen – das EoP Kartenspiel
  20:45 Oliver Sturm Functional Magic
Donnerstag 8:30 Christian Weyer WCF 4.0 SOAP Services: nachrichtenbasierte verteilte Anwendungen
  10:15 Christian Weyer WCF 4.0 Web/HTTP Services: Verteilte Anwendungen nach Webmachart
  14:00 Ingo Rammer Silverlight an Server: Geschäftsanwendungen mit WCF RIA Services
  15:45 Richard Blewett Building WCF Services with Workflow 4.0
  17:15 Ingo Rammer Grundlagen der Windows Phone 7 Anwendungsarchitektur
Feitag 9:30 Dominick Baier
Jörg Neumann
Christian Weyer
Power Workshop .NET End-to-End: verteilt, sicher, pragmatisch

 

Christian

CN innovation


Windows Forms and WPF Interop: Sharing WPF Resources

With WPF applications where the resources should not be locally with the application but shared with multiple applications, the WPF resources can be added to a library. Using the MergedDictionaries property of a ResourceDictionary the resources from another assembly can be referenced, for global resources this is usually done within the App.xaml file. Having a Windows Forms host that makes use of WPF controls it’s also possible to use shared resources for WPF styling. This blog post shows how this can be done.

Having resources in a shared library (the sample has the library named WpfStylesLib), shared resources (Dictionary1.xaml), with a WPF application the resources can be made available application-wide by adding the resource dictionary to the MergedDictionaries in the file App.xaml. To reference the shared library I’m using the relative Pack URI syntax. Following the / is the name of the assembly: WpfStylesLib. ;component following the assembly name means the assembly is referenced from the local assembly. Dictionary1.xaml is the resource name in the referenced assembly. Now all the resources defined within this dictionary can be used from the WPF application.

<Application x:Class="WPFResourceTest.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="MainWindow.xaml"> <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="/WpfStylesLib;component/Dictionary1.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources> </Application>

With a Windows Forms host usually there’s no App.xaml. It’s easy to add the resources from a shared library programmatically. Within the Main method of Program.cs I’m creating a WPF Application instance. To not get in conflict with the Windows Forms Application class I’ve added a namespace alias named WPF to System.Windows. After a new Application instance is created, Application.Current is set. Similar to the XAML code before I’m using the Resources property of the Application, reference the MergedDictionaries, and add a ResourceDictionary to it. Here I’m using the absolute Pack URL syntax to reference the resources in the shared assembly.

WPF.Application app = new WPF.Application(); WPF.ResourceDictionary dict = new WPF.ResourceDictionary(); dict.Source = new Uri("pack://application:,,,/StylesLib;component/Dictionary1.xaml"); WPF.Application.Current.Resources.MergedDictionaries.Add(dict);

More information on WPF and Windows Forms interop in my WPF workshop

Christian

CN innovation


BindingNavigator for WPF (Part 2–Using)

In my previous blog post I’ve shown a sample how to create a BindingNavigator for WPF that fulfills the functionality of the BindingNavigator that is available with Windows Forms. Part 2 of this series demonstrates how the BindingNavigator can be used.

User Interface

I’ve created a user interface that looks akin to the Windows Forms BindingNavigator by using the ribbon control. Of course the ribbon control allows for a much more enhanced UI, but this is another topic. The new look is shown in this screenshot:

image

For navigating through the records and adding, deleting, and saving I’ve defined one RibbonTab data with two RibbonGroup elements. The first RibbonGroup is for navigation, the second RibbonGroup for changing.

The elements within a RibbonGroup are mainly represented by RibbonButton elements, e.g. the buttons to move to the first and the previous record. For the UIs of the elements either the LargeImageSource or SmallImgeSource properties are set depending on the representation in the UI. The images are taken from the VS2010ImageLibrary that is part of Visual Studio 2010.

<ribbon:RibbonButton x:Name="firstButton" LargeImageSource="Images\MoveFirst.png" Label="First" Command="utils:DataCommands.FirstRecord" /> <ribbon:RibbonButton x:Name="prevButton" LargeImageSource="Images\MovePrevious.png" Label="Previous" Command="utils:DataCommands.PreviousRecord" />

Instantiating the BindingNavigator

A parent element of both the ribbon control and the controls that show the content of the record has a BindingNavigator set as the DataContext. Here, the property RacersNavigator returns a BindingNavigator.

<Grid DataContext="{Binding RacersNavigator}" utils:CommandBindingsAttachedProperty.RegisterCommandBindings= "{Binding CommandBindings}">

The property RacersNavigator returns a cached BindingNavigator if an instance is already created, otherwise a new object is instantiated where a data source in form of a Entity Framework ObjectQuery is assigned to the constructor.

private BindingNavigator racersNavigator; public BindingNavigator RacersNavigator { get { if (racersNavigator == null) { var data = GetRacersQuery(formula1Entities).Execute( MergeOption.AppendOnly); racersNavigator = new BindingNavigator(data); } return racersNavigator; } } private ObjectQuery<Racer> GetRacersQuery(Formula1Entities formula1Entities) { return formula1Entities.Racers; }

With the sample code I’m using the MVVM pattern with an implementation of the MVVM Light Toolkit from Laurent Bugnion. The root window has the DataContext set to a property of a view model locator which in turn returns a view model. The property RacersNavigator is the property of a view model. In case code-behind is preferred instead of MVVM, the RacersNavigator can be a implemented as a property of the code-behind code.

Commands

The BindingNavigator defines command bindings that define what command maps to what event handler. The commands used by the BindingNavigator are defined in the DataCommands class. Mapping UI actions to commands is done by setting the Command property as shown in the previous code snippet.

What also needs to be done is to map the command bindings to a UI element. As the BindingNavigator is not declared within XAML, this needs to be done manually. For mapping the command bindings to UI elements an attached property is used. This attached property gets the value from the CommandBindings property (of the BindingNavigator) that returns a CommandBindingCollection and adds the command bindings to the element where it is applied to (here to the Grid).

<Grid DataContext="{Binding RacersNavigator}" utils:CommandBindingsAttachedProperty.RegisterCommandBindings= "{Binding CommandBindings}">

Content

The container of the content controls needs to bind to the View property of the BindingNavigator. This View property returns the CollectionViewSource and thus allows content controls to bind to one element of the collection, and list controls to the complement list represented by the view.

<Grid DataContext="{Binding View}" HorizontalAlignment="Left" Margin="5,5,0,0" Name="grid1" VerticalAlignment="Top" Grid.Row="1">

To display the content no special action is needed. The controls as they are created from the data source window from Visual Studio can be used as they are.

<Label Content="Id:" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" /> <TextBox Grid.Column="1" Grid.Row="0" Height="23" HorizontalAlignment="Left" Margin="3" Name="idTextBox" Text="{Binding Path=Id, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="120" /> <Label Content="First Name:" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" /> <TextBox Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="3" Name="firstNameTextBox" Text="{Binding Path=FirstName, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="120" /> <Label Content="Last Name:" Grid.Column="0" Grid.Row="2" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" /> <TextBox Grid.Column="1" Grid.Row="2" Height="23" HorizontalAlignment="Left" Margin="3" Name="lastNameTextBox" Text="{Binding Path=LastName, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="120" />

 

Summary

As soon as the BindingNavigator is defined as was shown in the blog entry to create a BindingNavigator for WPF, it is easy to use it.

A UI for the commands must be implemented (e.g. by using the ribbon), the commands need to be fired, and the BindingNavigator takes the action.

Of course all the work of implementing the BindingNavigator is not necessary if Visual Studio LightSwitch is used Smile

Christian

CN innovation


BindingNavigator for WPF (Part 1 - Creating)

With my blog post about the new data source feature in Visual Studio 2010 for WPF applications, Luciano asked about a BindingNavigator counterpart to Windows Forms.The BindingNavigator that is available with Windows Forms is not here with WPF, and thus the automatically created UI from the data source window in Visual Studio 2010 lacks some functionality compared to Windows Forms.

With Windows Forms, the BindingNavigator offers a toolbar display as shown in the figure to navigate within records. The BindingNavigator class is connected to a BindingSource class. The BindingNavigator is responsible for the UI and allows the user to navigate through records, add new  or delete existing records, and to save changes.

WinFormsBindingNavigator

The BindingSource class has a data source associated that allows navigating with methods MoveFirst, MoveNext, MovePrevious, MoveLast, and an indexer, allows adding (AddNew), removing (Remove, RemoveAt, RemoveCurrent), and filtering items.

The WPF equivalence to the BindingSource class is the CollectionViewSource class. CollectionViewSource is defined in the namespace System.Windows.Data. CollectionViewSource has a source and view connected that can be accessed via Source and View properties. A view implements the ICollectionView interface with methods for navigating (MoveCurrentTo, MoveCurrentToFirst, MoveCurrentToLast, MoveCurrentToNext….

For this blog post I’m creating a sample of a WPF BindingNavigator. Contrary to the Windows Forms BindingNavigator, the BindingNavigator here has no UI but otherwise offers the functionality of the Windows Forms BindingNavigator. Any UI, for example a ribbon control, can be used that fires commands where the BindingNavigator reacts.

With a BindingNavigator defined as a custom control it would also be possible to define a default UI that can be customized with a template. Maybe I’m showing this in a future blog post.

BindingNavigator adapts CollectionViewSource

The BindingNavigator class receives a data source collection in the constructor and adapts the WPF CollectionViewSource. A CollectionViewSource is instantiated in the constructor, and uses it on navigation.

public class BindingNavigator : INotifyPropertyChanged { private CollectionViewSource cvs; public BindingNavigator(IEnumerable dataSource) { cvs = new CollectionViewSource(); cvs.Source = dataSource; InitializeCommands(); }

To access all the elements from the collection that is managed by the CollectionViewSource, the View property of the BindingNavigtor allows direct access to the properties of the ICollectionView interface. This makes it possible the retrieve and change values from objects just as the BindingNavigator wouldn’t be in between.

public ICollectionView View { get { return cvs.View; } }

Custom Commands

Instead of defining Click event handlers, the sample uses commands. This makes it possible to define the commands independent of the UI. I’ve defined custom commands for this sample. All the commands used by the BindingNavigator are defined by the DataCommands class.

DataCommands defines all the commands that should be used with navigation of records.

Instead of defining custom commands, it would be possible to use the WPF predefined NavigationCommands and ApplicationCommands. For example, NavigationCommands.NextPage and NavigationCommands.PreviousPage could be used instead of DataCommands.NextRecord and DataCommands.PreviousRecord.

public static class DataCommands { private static object syncRoot = new object(); private static RoutedUICommand[] cachedCommands = new RoutedUICommand[Enum.GetNames(typeof(CommandId)).Count()]; private enum CommandId : byte { NullRecord = 0, NextRecord = 1, PreviousRecord = 2, FirstRecord = 3, LastRecord = 4, GoToRecord = 5, AddRecord = 6, Save = 7, DeleteRecord = 8 }

The enumeration is used with each static property that represents a command. The code snippet just shows the Save property, all the other command properties are similar. The method EnsureCommand returns the command instance of type RoutedUICommand taking a cached version if the command instance was previously created.

public static RoutedUICommand Save { get { return EnsureCommand(CommandId.Save); } } private static RoutedUICommand EnsureCommand(CommandId idCommand) { RoutedUICommand command = null; lock (syncRoot) { command = cachedCommands[(int)idCommand] ?? (cachedCommands[(int)idCommand] = new RoutedUICommand(Enum.GetName(typeof(CommandId), idCommand), Enum.GetName(typeof(CommandId), idCommand), typeof(DataCommands))); } return command; }

Navigation

The functionality offered by the BindingNavigator mainly is for navigation – of course. For this functionality the BindingNavigator makes use of commands. The InitalizeCommands method is called from within the constructor and adds all CommandBindings to a CommandBindingCollection.

public void InitializeCommands() { var nextCommand = new CommandBinding(DataCommands.NextRecord, OnNextRecord); commandBindings.Add(nextCommand); var previousCommand = new CommandBinding(DataCommands.PreviousRecord, OnPreviousRecord); commandBindings.Add(previousCommand); var firstCommand = new CommandBinding(DataCommands.FirstRecord, OnFirstRecord); commandBindings.Add(firstCommand);

The CommandBindingCollection can be accessed from the outside via the CommandBindings property.

private readonly CommandBindingCollection commandBindings = new CommandBindingCollection(); public CommandBindingCollection CommandBindings { get { return commandBindings; } }

The sample BindingNavigator doesn’t have a user interface and cannot be used from XAML. If the BindingNavigator would be a custom control offering a user interface, the command can be added via the CommandManager to have it available for UI controls. In this scenario the bindings must be added from the outside which is done here via an attached property that is shown later.

With the constructor of the CommandBinding class a command is bound to a handler. For example, the DataCommands.NextRecord command is bound to the handler method OnNextRecord. OnNextRecord is a static method that finds the instance of the BindingNavigator from the DataContext property of the sender that fires the command. Then the OnNextRecord instance method is invoked.

public static void OnNextRecord(object sender, ExecutedRoutedEventArgs e) { Contract.Requires(sender is FrameworkElement, "sender must be a FrameworkElement"); Contract.Requires((sender as FrameworkElement).DataContext is BindingNavigator, "sender.DataContext must be a BindingNavigator"); BindingNavigator nav = (sender as FrameworkElement).DataContext as BindingNavigator; if (nav != null) nav.OnNextRecord(); }

The instance method OnNextRecord makes use of the CollectionViewSource to navigate to the next record. Also, the property CurrentPosition that can be used with data binding might change on moving to the next record, and thus the PropertyChanged event is fired via the RaisePropertyChanged method.

 

private void OnNextRecord() { this.cvs.View.MoveCurrentToNext(); if (cvs.View.IsCurrentAfterLast) cvs.View.MoveCurrentToLast(); RaisePropertyChanged("CurrentPosition"); }

Binding Commands via an Attached Property

As previously mentioned, for the commands to be active, they must be added to a XAML element. This is done with the attached property RegisterCommandBindings that is defined in a helper class.

public class CommandBindingsAttachedProperty : DependencyObject { public static readonly DependencyProperty RegisterCommandBindingsProperty = DependencyProperty.RegisterAttached( "RegisterCommandBindings", typeof(CommandBindingCollection), typeof(CommandBindingsAttachedProperty), new PropertyMetadata(null, OnRegisterCommandBindingChanged)); public static void SetRegisterCommandBindings(UIElement element, CommandBindingCollection value) { element.SetValue(RegisterCommandBindingsProperty, value); } public static CommandBindingCollection GetRegisterCommandBindings( UIElement element) { return (CommandBindingCollection)element.GetValue( RegisterCommandBindingsProperty); } private static void OnRegisterCommandBindingChanged(object sender, DependencyPropertyChangedEventArgs e) { UIElement element = sender as UIElement; if (element != null) { CommandBindingCollection bindings = e.NewValue as CommandBindingCollection; if (bindings != null) element.CommandBindings.AddRange(bindings); } } }

Summary

To get a BindingNavigator to WPF that already exists for a long time just a simple class is needed that adapts the CollectionViewSource and defines commands that navigates through the records by using the CollectionViewSource.

Now all what’s needed is to define a UI that fires the commands. This is shown in the next blog post by using the WPF ribbon control.

 

Christian

CN innovation


Visual Studio LightSwitch–Another Level of Abstraction?

Visual Studio LightSwich is a new tool to create data-centric Silverlight applications as I’ve already written about in a previous blog post.

Currently there’s a lot of discussion going on about this tool, in regard to “non-programmers”, “non-thinkers”, “Microsoft doesn’t get it”…

For myself I love writing code, but “the best code is the one you don’t write”.

I’ve written and loved writing Assembler code. I’ve done C when C was discussed as too much “high-level”. Then C++ had too much overhead for many contrary to C, reasoning object-orientation is not needed. Nowadays trusting the garbage collector from .NET has become normal. We write XAML and C# code. Of course there are still scenarios where Assembler and C has its places.

It was really fun to teach a one-week ATL course where after the week major issues to discuss have been templates, dual, dispatch, custom interfaces, different apartment models like STA, MTA, TNA, and the best we could get after a week probably was calling very simple components across the network. Nowadays in a course week it’s possible to create fancy UIs calling services across a network, using complex databases… I wouldn’t want to write this with C or pure assembler code.

Abstraction goes on and on and on.

Visual Studio LightSwitch allows doing fancy UIs calling services across the network, using complex databases… without a single line of code. Probably in reality several lines of code are still required as there’s a C# and a Visual Basic template for LightSwitch inside Visual Studio, but the code lines will be reduced.

Visual Studio LightSwitch is not the first tool to offer such functionality. Several others failed doing so. What’s different now?

Reason other tools failed were e.g. scalability. Some tools could be used in a single-user scenario but failed as soon as multiple users were accessing the same database.

Visual Studio LightSwitch is based on .NET technologies, probably uses stateless services, well-known patterns to reach scalability. Deploying to Windows Azure just by changing configuration values the number of systems answering the client requests can be simple increased. Probably manual code can be written much more efficient in that half of the number of systems could get the same overall performance compared to the code that is generated, but it might be cheaper to not write the code. In regard to scalability with Visual Studio LightSwitch I’m seeing more issues in defining scalable databases.

As Visual Studio LightSwitch is based on .NET technologies, I expect enough extension possibilities where the extensions are done by “real developers” to have this technology for a broad range of scenarios.

Of course every tool can and will be misused. For example, when a city changes the postal code which means changing thousands of customers, would it be a good way to use a DataReader to read every one of these customers, and to an UPDATE statement for each one? Or using the ADO.NET Entity Framework to read all the customers into the data context, changing the postal code, and doing a SaveChanges to the database? Or just do a single SQL UPDATE statement instead? Every tool can and will be used in scenarios it isn’t meant to do. I’m not expecting Visual Studio LightSwitch as the tool to do every data-centric application.

One big issue I’ve seen many times with tools that allows much of the functionality by a designer is versioning. If creating a big solution with this tool, how can it be migrated to the next version? Will this be seamless by just opening the solution with a new version? Does it require to redo a lot again? What if many third-party components are used? Does it require to wait until the 3rd party components are moved forward to the next version before migrating?

This needs to be seen how it works out with Visual Studio LightSwitch. Probably it’s best not starting with a big solution but with smaller scenarios. What extensions are required, what’s already in the box?

Christian


Data-Centric Silverlight Applications with Visual Studio LightSwitch

Visual Studio gets a new family member – Visual Studio LightSwitch!

The previous post on data-centric WPF applications showed some enhancements of Visual Studio 2010 to use data sources with WPF applications. Visual Studio LightSwitch goes big steps further with Silverlight to create 2-tier desktop or 3-tier desktop or Web applications.

The data source window from Visual Studio 2010 helps with writing data-centric applications as user interfaces can be created out from a data source just by drag and drop after defining in a graphical editor what UI elements should be used for what data. The data source window here gives a few options such as using grids, lists, or details, and allows selecting labels, text boxes, combo boxes or various other controls. The code-behind to retrieve the data or do updates usually needs to be custom implemented.

Developer’s aren’t the only ones writing applications – I never forget how Microsoft Access was (is) used!

With Visual Studio LightSwitch the complete application can be done with the help of a designer tool; writing just a few lines of code. The Visual Studio templates for Visual Studio LightSwitch offer C# and Visual Basic code.

Visual Studio LightSwitch supports data from lot of different sources, e.g. SQL Server (of course also SQL Azure), SharePoint, WCF RIA Services…

Instead just having grids, lists, details to define how the data should be displayed many more pre-built screen templates are available: new data, search data, details, editable grid, list and details.

The outcome from Visual Studio LightSwitch just by selecting a checkbox is a 2-tier desktop, 3-tier desktop, or 3-tier Web application.

Visual Studio LightSwitch also integrates with Office 2010. For example data can be exported to Excel, Word document templates can be used, and with Outlook it’s possible to integrate workflows because on arriving emails.

What if the features and templates from Visual Studio LightSwitch are not enough? I expect many scenarios where this is the case. Visual Studio LightSwitch can be extended by custom templates, controls… There’s a big market on writing extensions, and some 3rd party providers are already working on extensions, e.g new skins, adding tough functionality for the application…

Remember the times where Visual Basic users just used drag&drop to connect some ActiveX controls? I’m seeing two kind of people working with this technology: just using it, or writing extensions.

Can’t wait to try this out and find out about customizations and all the features that Visual Studio LightSwitch is based on. A public beta of Visual Studio LightSwitch will be available on 23-August.

This could be a new way to write fast applications for Windows Azure! Hosting the application in Windows Azure, using the SQL Azure database.

More information on Visual Studio LightSwitch:

Jason Zander’s Introducing Microsoft Visual Studio LightSwitch

Visual Studio LightSwitch

LightSwitch Developer Center

Visual Studio LightSwitch Team Blog

 

Christian


Data-Centric WPF Applications with Visual Studio 2010

Data Sources from Visual Studio 2010 allows for easily creating user interfaces for WPF applications to read/write data. Previously, with Visual Studio 2008 this was only available for Windows Forms applications, and used the DataSet behind the scenes. Now WPF is supported as well, and an Entity Framework can be used.

After creating a WPF application, a data source can be created. The data source that can be selected from the Data Source Configuration Wizard allows accessing  Database, a Service, an Object, and SharePoint.

image

After selecting the data source either the old DataSet can be used for accessing data, or a Entity Data Model can be created.

image

The Data Sources window now allows if data should be displayed within a DataGrid, as list or detail information. Then it’s possible to define the UI elements for each property of the DataSource, e.g. Label, TextBox, ComboBox, TextBlock… For a DateTime data type per default the DatePicker is selected. It’s also possible to add custom controls.

image

By drag&drop from the Data Sources window to the WPF designer the UI elements are added to the XAML code. The UI elements that are added are data-bound to CollectionViewSource elements. CollectionViewSource is a proxy to CollectionView that itself allows grouping, sorting, filtering, and navigation.

 

<Window.Resources> <CollectionViewSource x:Key="racersViewSource" d:DesignSource="{d:DesignInstance my:Racer, CreateList=True}" /> <CollectionViewSource x:Key="racersRaceResultsViewSource" Source="{Binding Path=RaceResults, Source={StaticResource racersViewSource}}" /> </Window.Resources>

 

In the code-behind generated code a query is created across the object context to retrieve data from the database.

 

private ObjectQuery<Racer> GetRacersQuery(Formula1Entities formula1Entities) { // Auto generated code ObjectQuery<Racer> racersQuery = formula1Entities.Racers; // Update the query to include RaceResults data in Racers. You can modify this code as needed. racersQuery = racersQuery.Include("RaceResults"); // Returns an ObjectQuery. return racersQuery; }

 

This query is used when loading the Window to assign the Source property of the CollectionViewSource.

 

private void Window_Loaded(object sender, RoutedEventArgs e) { Formula1Entities formula1Entities = new Formula1Entities(); // Load data into Racers. You can modify this code as needed. CollectionViewSource racersViewSource = ((CollectionViewSource)(this.FindResource("racersViewSource"))); ObjectQuery<Racer> racersQuery = this.GetRacersQuery(formula1Entities); racersViewSource.Source = racersQuery.Execute(MergeOption.AppendOnly); }

 

The generated code might not be the one exactly needed. For very simple scenarios it just might be enough and just needs small tweaks and additions to write data to the database.

In most scenarios the code needs bigger changes and additions. This technology still might be a good use for a start to create UI elements based on some data and change it afterwards. The generated XAML code for the UI can also be copied to different projects.

Christian