Posts Tagged ‘C#’

The dream of "half-automatic" Automation Properties

Friday, May 2nd, 2008

Everyone who has worked with WPF knows the interface INotifyPropertyChanged. It only defines the PropertyChanged-event, that should be called when a property’s value has been changed. The PropertyChanged-event is used by WPF’s Data Binding.

Normally a class fires the event in the set-Accessors of its properties. And that’s the problem why you can’t use Automation Properties for classes that implement INotifyPropertyChanged.

Let’s take a very simple example, a Person-class, that only contains a Name-Property:

public class Person
{
  public string Name { get; set; }
}

If you now want to implement INotifyPropertyChanged, you have to use a property backed explicitly with a private field:

public class Person:INotifyPropertyChanged
{
  private string _name;
  public string Name
  {
    get { return _name; }
    set
    {
      _name = value;
      if (PropertyChanged != null)
        PropertyChanged(this,
          new PropertyChangedEventArgs("Name"));
    }
  }
  public event PropertyChangedEventHandler PropertyChanged;
}

Wouldn’t it be nice to use a "half-automatic"-Property in the code-snippet above? The private-Field _name and the get-Accessor could be created. A keyword would be necessary to access the private-Field in the set-Accessor. I think the keyword could be autoField or something like that. If Microsoft would implement "half automatic"-Properties in C# 3.5 or 4.0, you could create the Person-class as below. But keep in mind that this is just a dream, I don’t know if something like this is planned, so the Person-class implemented like below wouldn’t work (today):

public class Person:INotifyPropertyChanged
{
  public string Name {
    get;
    set
    {
      autoField = value;
      if (PropertyChanged != null)
        PropertyChanged(this,
          new PropertyChangedEventArgs("Name"));
    }
  }

  public event PropertyChangedEventHandler PropertyChanged;
}

What do you think of “half-automatic”-Properties? Would it be a useful feature for you?

C# 3.0 and WPF’s ListView

Wednesday, December 12th, 2007

In many applications you want to fill up a ListView or a GridView with some data. In WPF applications you set the View-Property of the ListView to a GridView to show the data nicely in columns. In most cases you have an entity class (think of it as a "real" entity class or a DataRow as part of a DataTable), and objects of this class should be represented in a row of the GridView. In WPF the DisplayMemberBinding-Property of each GridViewColumn is bound to a property of the entity class, so objects of the entity class can be easily added to the ListView and are displayed correctly in the GridViewColumns. But…

The problem (… the problem is more code as you want to have) begins, when you have no entity class and your data is stored in objects of different classes, maybe only in some variables, and you just want to display the data in one row of the ListView. If your variables have a relation to each other, it’s semantically correct to put them into one row of the ListView, displayed in different GridViewColumns. But to display the data in the ListView, you have to create a dummy entity class that contains your data. There’s no other way!

… no other way with C# 2.0. But now we have C# 3.0, and things can get much easier, cause the compiler can create nearly everything for you. :-) To show you how some C# 3.0 features can help you for the problem above with the dummy entity class, I have to step some months back in time and pick out a small sample that exactly shows the necessity of creating a dummy entity class.

Some months ago I created a small WPF application (.NET 3.0 and C# 2.0) to show developers how Routed Events are routed through the Element Tree. The application contains a Button and a ListView. The Button contains a StackPanel and inside this StackPanel is a Rectangle. Below the Window1.xaml:

<Window x:Class="RoutedEventsBeispiel.Window1"
xmlns=="http://schemas.microsoft.com/winfx/2006/xaml/.."
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="RoutedEventsBeispiel" Height="450" Width="500">
 <Grid>
  <Grid.RowDefinitions>
   <RowDefinition Height="Auto"/>
   <RowDefinition/>
  </Grid.RowDefinitions>
  <Button x:Name="button1" Width="100"
          Height="100" Margin="5">
   <StackPanel x:Name="stackPanel1" Background="Black">
    <Rectangle x:Name="rectangle1" Margin="10"
                 Fill="Red" Width="50" Height="50"/>
   </StackPanel>
  </Button>
  <ListView x:Name="listView" Grid.Row="1">
   <ListView.View>
    <GridView>
     <GridViewColumn Header="RoutedEvent"
       DisplayMemberBinding="{Binding RoutedEventName}"/>
     <GridViewColumn Header="Sender"
       DisplayMemberBinding="{Binding Sender}"/>
    </GridView>
   </ListView.View>
  </ListView>
 </Grid>
</Window>

Especially take a look at the DisplayMemberBinding-Property of the two GridViewColumns in the Window1.xaml above. To represent some data in this ListView, the Data must be represented by an object that has a Property RoutedEventName and a Property Sender. Therefore the Dummy class joins the game. Of course the class could be named in a better way like "RoutedEventInfo", but I decided to name it Dummy, because later with C# 3.0 this class won’t be necessary anymore:

public class Dummy
{
  private string _sender;
  private string _routedEventName;

  public string Sender
  {
    get { return _sender; }
    set { _sender = value; }
  }
  public string RoutedEventName
  {
    get { return _routedEventName; }
    set { _routedEventName = value; }
  }
}

In the constructor of Window1 in the codebehind Window1.xaml.cs a general Eventhandler for the Events UIElement.PreviewMouseLeftButtonDown and UIElement.MouseLeftButtonDown is added to the Window, the Button, the StackPanel and the Rectangle. The third parameter of the AddHandler-Method is always set to true. This true stands for "handledEventsToo", so the GeneralOnMouseDown-Eventhandler is called even if any EventHandler has set the Handled-Property of the RoutedEventArgs to true (That’s exactly what the ButtonBase class does internally with the MouseLeftButtonDown-Event, when the ButtonBase class raises its own Click-Event. So the third parameter is necessary here to get the application show the tunneling and bubbling of the events like expected)

public partial class Window1 : System.Windows.Window
{
  public Window1()
  {
   InitializeComponent();

   this.AddHandler(UIElement.PreviewMouseLeftButtonDown…,
    new RoutedEventHandler(GeneralOnMouseDown), true);
   this.AddHandler(UIElement.MouseLeftButtonDownEvent,
    new RoutedEventHandler(GeneralOnMouseDown), true);
   button1.AddHandler(UIElement.PreviewMouseLeftButtonDown…,
    new RoutedEventHandler(GeneralOnMouseDown), true);
   button1.AddHandler(UIElement.MouseLeftButtonDown…,
    new RoutedEventHandler(GeneralOnMouseDown), true);
   stackPanel1.AddHandler(UIElement.PreviewMouseLe…,
    new RoutedEventHandler(GeneralOnMouseDown), true);
   stackPanel1.AddHandler(UIElement.MouseLeftButton…,
    new RoutedEventHandler(GeneralOnMouseDown), true);
   rectangle1.AddHandler(UIElement.PreviewMouseLeft…,
    new RoutedEventHandler(GeneralOnMouseDown), true);
   rectangle1.AddHandler(UIElement.MouseLeftButton…,
    new RoutedEventHandler(GeneralOnMouseDown), true);
  }
void GeneralOnMouseDown(object sender,RoutedEventArgs e)
  {
   if (sender is Window1 
    && e.RoutedEvent==UIElement.PreviewMouseLeftButton…)
   {
     listView.Items.Clear();
   }
   Dummy d = new Dummy();
   d.Sender = sender.GetType().Name;
   d.RoutedEventName = e.RoutedEvent.Name;
   listView.Items.Add(d);
  }
}

The general Eventhandler GeneralOnMouseDown clears the Items of the ListView if the sender is a Window1 instance and the routed event is the tunneling event PreviewMouseLeftButtonDown. After that, it creates an instance of type Dummy, sets its Sender- and RoutedEventName-Property, and adds the Dummy instance to the ListView.

When you click on the red Rectangle located inside of the black StackPanel that is located inside of the Button, the ListView is filled up with Dummy objects, and it shows us, in which order the routed events are raised. The PreviewMouseLeftButtonDown-Events tunnels down from the Window1 to the Rectangle, then the MouseLeftButtonDown-Event bubbles up to the Window1.

20071118_RoutedEvents

That’s the application like I developed it with C# 2.0 and .NET 3.0. The need of the Dummy class is only necessary, because I got two string variables (the name of the routed event and the type name of the sender) that I have to put into one object, and this one object is put into the ListView. The GridViewColumns are bound to the Properties Sender and RoutedEventName of the object inside the ListView, so the Dummy objects are displayed like expected in the correct GridViewColumns.

Now how can I shorten my code with C# 3.0? We just focus on the GeneralOnMouseDown-Eventhandler and the Dummy-class. To add a Dummy object to the ListView, you can just use the Object Initializer to get it done in one instead of four statements:

listView.Items.Add(new Dummy() {
    Sender = sender.GetType().Name,
    RoutedEventName = e.RoutedEvent.Name });

Of course you could alternatively add a constructor to the Dummy-class instead of using an object initializer and you would reach a similar effect. But not always you’re the owner of such a Dummy-class and so you won’t be able to add a constructor. Even if you’re the owner of the Dummy-class, I think you like it to write less code (if you’re not paid per lines of code :-) ). With object initializers you won’t have to create many different constructors.

Now take a look at the Dummy class itself. It could be much shorter, if you use the Automation Properties of C# 3.0 (the IL-Code will still look the similar like before). With automation properties, the compiler creates the backing private fields for the specified properties:

public class Dummy
{
  public string Sender { get; set; }
  public string RoutedEventName{get;set;}
}

We can go even further.

If you’ve read the C# 3.0 specification, you’ve also read about Anonymous Types. So let’s go ahead one more step. Anonymous types are not only a feature that is good to use in LINQ-statements. In this small application here we could throw the Dummy class away and instead of Dummy objects we can add anonymous type objects to the ListView. The anonymous type must contain the properties Sender and RoutedEventName. So without the Dummy class you could fill up the ListView in the GeneralOnMouseDown-Eventhandler just with anonymous types like below, and the application still works the same way:

void GeneralOnMouseDown(object sender,RoutedEventArgs e)
{
  if (sender is Window1 && e.RoutedEvent==…)
    listView.Items.Clear();

  listView.Items.Add(new { Sender = sender.GetType().Name,
    RoutedEventName = e.RoutedEvent.Name });
}

In the background, the compiler creates an Anonymous class, that contains two properties Sender and RoutedEventName. So in IL you’ll find a class created from the anonymous type used above. But that’s not your problem, your C# Code itself gets much shorter.

The cool thing about C# 3.0 and Visual Studio 2008 is that you can use these C# 3.0 features to build .NET 2.0 applications (Of course for WPF applications you need at least version 3.0 of .NET). But be careful when using C# 3.0 features for .NET 2.0 apps. E.g. language enhancement features like LINQ are based on Extension Methods located in assemblies introduced with .NET 3.5. :-)

TechEd Developers 2007 in retrospect - Tuesday

Saturday, November 17th, 2007

On the second day at TechEd, the first session I joined had the title "Cool Looking 3D visualizations with Windows Presentation Foundation (WPF)" (Speaker: Dennis Vroegop).

The WPF has a "built-in" 3D-API, and this session showed what you can do with 3D in your business applications. The 3D-API of WPF isn’t adequate for great 3D Games. For Games you should use Managed DirectX that has a much better performance than WPF’s 3D-API (which is build on a "Media Integration Layer" (Milcore) that is built on top of DirectX). WPF’s 3D-API is an easy way to bring some great 3D effects to your business applications. This session showed beside the basics of 3D an example how 3D can be used for a better data representation. The used example showed a 3D map and represented product-data for different locations as 3D-objects.

LINQ to SQL: Accessing Relational Data with Language was the session I joined next, speaker was Luca Bolognese. LINQ to SQL is the easiest way to access a relational database with .NET 3.5. In LINQ to SQL entity classes are mapped directly to tables in the database. For each table a class. To query a database a developer hasn’t to know anything about SQL. The query is defined in C# with the LINQ-Syntax introduced in C# 3.0. The SQL sent to the database is generated automatically. Let’s look at a very simple example to load some data.

To load data with LINQ to SQL, the first thing you have to do is to add a reference to the assembly System.Data.Linq.dll to your project and then create your entity classes. The entity classes are mapped to a table in the database via the attributes Table and Column contained in the namespace System.Data.Linq.Mapping. Of course Visual Studio 2008 contains a designer, that allows you to drag’n'drop tables from the server explorer to the designer surface, and it’ll create the entity classes for you. In this example I’ll just use a manually created class:

[Table(Name="Friends")]
class Friend
{
  [Column(IsPrimaryKey=true)]
  public Guid FriendID;
  [Column]
  public string Name;
  [Column]
  public int Age;
}

As shown above, the Class Friend maps to the table Friends as specified with the TableAttribute. You could also specify the TableAttribute without setting the Name-Property, then your classname must match exactly the table name in the database. The table Friends in the database contains the columns FriendID, Name and Age. You see exactly the same columns in the Friend class. The ColumnAttribute also has a Name-Property that you can use if your .NET field or property doesn’t match the columnname from the table in the database. The column FriendID is additionally marked as primary key. Only those fields/properties you’ve marked with an ColumnAttribute are persisted in the database and could be loaded from database via LINQ to SQL. Ok, so far we’ve created a Friend class mapping to a Friends table in the database.

Now we can already connect to the Database and query the Friends table by using the DataContext class. The DataContext is used similar to the ADO.NET Connection. In fact the DataContext constructor takes a connection string and internally uses an IDbConnection. The DataContext is responsible to translate the queries you write in LINQ against your objects to SQL. To view the SQL the DataContext has generated for you, assign a TextWriter to its Log-Property. In the following snippet I’ve just assigned the standard output stream of the console to the Log-Property of the DataContext. I’ve passed in a connection string for the database “hubethomsDB” in my local SQLEXPRESS instance to the constructor of the DataContext:

DataContext ctx = new DataContext(
  @"Server=.\SQLEXPRESS;Database=hubethomsDB");

ctx.Log = Console.Out;    

In LINQ to SQL every table is represented by a Table-Collection of type System.Data.Linq.Table<TEntity>. As the name implies, the Table itself is identified by the entity class. Back to our sample, you get a Table-Collection for the table Friends by calling the generic Method GetTable<TEntity> on the DataContext and give the Method the Friend entity as the generic argument:

Table<Friend> friends = ctx.GetTable<Friend>();

On the received Table-Collection, you can create a query in LINQ. And now there’s a big difference to SQL. The query isn’t executed by the statement you see below, it’s only created.

var query = from f in friends
            where f.Age < 30
            select f;

The query gets executed, when you iterate over it, not before!!!

foreach (var friend in query)
{
  Console.WriteLine(friend.ToString());
}

The SQL generated by the DataContext is shown in the console window below. As you can see in the generated SQL, the data is filtered on the database and not in .NET.

20071117_LINQToSQL

Luca Bolognese said in his session, that Microsoft has tried every possible query and the DataContext was able to create a good SQL statement out of it. The tests have been done by people working for long times in the sqlserver team. Time to try some real complex queries on it and check it out.

What is the benefit of LINQ to SQL, when classes are mapped directly to tables?

The biggest benefit out of LINQ to SQL is that a developer hasn’t to know anything about SQL, he can specify and execute his query directly in C#.

Conclusion: I haven’t tested real complex SQL statements with LINQ to SQL up to now. Interesting are also things like indexes used by the generated query etc.