Beginners Guide To Threading

Beginners Guide To Threading In .NET

I have just started a series of articles over at codeproject on threading in .NET.

I don’t know the exact schedule, but it may end up being something like

I hope this will help some folk learn how to use threads. It’s a complex subject, so hopefully these articles will be easy enough for folk to follow.

I certainly hope so anyway.

Advertisements
CodeProject, WPF

Binding.StringFormat

One of my WPF Disciple buddies just sent an email around asking about Binding.StringFormat. Mmm so now there is a Binding.StringFormat. Neat. So we can now do things like the following. If you want to see all the new stuff in the .NET 3.5 BETA, check out Scott Guthries blog, using this link .NET 3.5 SP 1

 

   1:      <Grid>
   2:          <TextBlock Text="{Binding ElementName=slider1,
   3:              Path=Value, SringFormat='Amount: {0:0.000}'}"
   4:              Height="21" Margin="44,37,65,0"
   5:              VerticalAlignment="Top" />
   6:  
   7:          <Slider Value="58″ Margin="53,77,50,0"
   8:              Name="slider1" Height="24"
   9:              VerticalAlignment="Top"
  10:              Maximum="100" />
  11:      </Grid>

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

Introduction

Silverlight 2.0 DeepZoom

I have not done too much with the new Silverlight 2.0 Beta, but one area that interested me was the new DeepZoom capabilities.

DeepZoom is based on the idea of a MultiScaleImage, where the user is able to compose a single (or collage of images) and pan around and zoom in/out, and the image quality remains fairly good at all zoom levels. I believe this used to be called "Sea Dragon" and Microsoft purchased Sea Dragon, and re-branded it DeepZoom.

To see what DeepZoom looks like have a look at the Vertigo showcase memorabilia.hardrock.com/ site. This gives you a feel.

Anyway, yesterday I set about trying to get it working in my own Silverlight 2.0 app.

And guess what, it’s not quite as intuitive as one would think.

For example I had (probably quite wrongly) assumed that the behaviour shown at the Vertigo showcase site was the default behaviour for a MultiScaleImage, and it’s not. By default the MultiScaleImage does nothing special at all for dragging/zooming, you have to do this yourself.

Most of it is simple CLR mouse stuff, there is however one area that wasn’t clear to me, which is the scrollwheel on the mouse, these are not natively available in Silverlight. You need to hook these events straight from your chosen browser into CLR code. Now again Vertigo being the community minded folk that they are, had a codeplex page which shows how to do this.

So to show what I did to get DeepZoom working for my own app, I followed these steps:

  1. Created a Deep Zoom composer project and exported it (using DeepZoom Composer)
  2. Created a Silverlight 2.0 app in VS2008
  3. Adding a MultiScaleImage  in the Silverlight app
  4. Copied the Deep Zoom composer project output to the web projects ClientBin, and used the Vertigo MultiScaleImageWrapper class to capture mousewheel browser events
  5. Changed the Uri that I need to point to for my Deep Zoom composer project  output (ClientBin/….)

And then I was in business.

You can read the entire article that I wrote over codeproject using this link DeepZoom codeproject article

WPF

Dragging Element In A Canvas

You know when there is something you have done a million times, but for the life of you, you just can’t seem to be able to remember how to do it. Well responding to mouse movements, is my bug bear.

Today I had to drag an element in a container in WPF, and try as I did, I just couldn’t bend it to my will, so I went home and tried again. And this time it worked, so I am recording it for ever more, so that when I have to do this again, it will be there in 1.

The full XAML is as follows:

   1:  <Window x:Class="WpfApplication1.Window1"
   2:      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:      Title="Window1" Height="300" Width="300">
   5:   
   6:          <Canvas Name="canv1">
   7:              <Rectangle Canvas.Top="8" Canvas.Left="8"
   8:      Width="32" Height="32" Fill="LightPink" />
   9:              <Ellipse Canvas.Top="8" Canvas.Left="48"
  10:      Width="40" Height="16" Fill="Tan" />
  11:          </Canvas>
  12:  </Window>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

And here is the full code behind (C#)

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Text;
   5:  using System.Windows;
   6:  using System.Windows.Controls;
   7:  using System.Windows.Data;
   8:  using System.Windows.Documents;
   9:  using System.Windows.Input;
  10:  using System.Windows.Media;
  11:  using System.Windows.Media.Imaging;
  12:  using System.Windows.Navigation;
  13:  using System.Windows.Shapes;
  14:   
  15:  namespace WpfApplication1
  16:  {
  17:      /// <summary>
  18:      /// Interaction logic for Window1.xaml
  19:      /// </summary>
  20:      public partial class Window1 : Window
  21:      {
  22:   
  23:          Point startPoint;
  24:          Point selectedElementOrigins;
  25:          bool IsDragging;
  26:          UIElement selectedElement;
  27:   
  28:   
  29:          public Window1()
  30:          {
  31:              InitializeComponent();
  32:              canv1.PreviewMouseLeftButtonDown += Canvas_PreviewMouseLeftButtonDown;
  33:              canv1.PreviewMouseMove += Canvas_PreviewMouseMove;
  34:              canv1.PreviewMouseLeftButtonUp += Canvas_PreviewMouseLeftButtonUp;
  35:          }
  36:   
  37:          /// <summary>
  38:          /// stop dragging and release mouse capture
  39:          /// </summary>

42: void Canvas_PreviewMouseLeftButtonUp(object sender,

  43:              MouseButtonEventArgs e)
  44:          {
  45:              if (canv1.IsMouseCaptured)
  46:              {
  47:                  IsDragging = false;
  48:                  canv1.ReleaseMouseCapture();
  49:                  e.Handled = true;
  50:              }
  51:          }
  52:   
  53:          /// <summary>
  54:          /// Works out the delta for the mouse movement
  55:          /// and moves selected element by delta
  56:          /// </summary>
  57:          void Canvas_PreviewMouseMove(object sender, MouseEventArgs e)
  58:          {
  59:              
  60:              if (canv1.IsMouseCaptured)
  61:              {
  62:                  //if dragging, get the delta and add it to selected 
  63:                  //element origin
  64:                  if (IsDragging)
  65:                  {
  66:                      Point currentPosition = e.GetPosition(canv1);
  67:                      double elementLeft = (currentPosition.X - startPoint.X) + 
  68:                          selectedElementOrigins.X;
  69:                      double elementTop = (currentPosition.Y - startPoint.Y) + 
  70:                          selectedElementOrigins.Y;
  71:                      Canvas.SetLeft(selectedElement, elementLeft);
  72:                      Canvas.SetTop(selectedElement, elementTop);
  73:                  }
  74:              }
  75:          }
  76:   
  77:          /// <summary>
  78:          /// Obtain start point and selected element, and record
  79:          /// selected element original point
  80:          /// </summary>
  81:          void Canvas_PreviewMouseLeftButtonDown(object sender, 
  82:              MouseButtonEventArgs e)
  83:          {
  84:              //Dont act apon events from parent element
  85:              if (e.Source == canv1)
  86:                  return;
  87:   
  88:              if (!IsDragging)
  89:              {
  90:                  startPoint = e.GetPosition(canv1);
  91:                  selectedElement = e.Source as UIElement;
  92:                  canv1.CaptureMouse();
  93:   
  94:                  IsDragging = true;
  95:   
  96:                  selectedElementOrigins =
  97:                      new Point(
  98:                          Canvas.GetLeft(selectedElement),
  99:                          Canvas.GetTop(selectedElement));
 100:              }
 101:              e.Handled = true;
 102:          }
 103:      }
 104:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

There so now we have it for ever. Amen, here is a small demo project (VS2008) drag.zip

C#, WPF

Using the System.AddIn namespace

.NET .3.5 created a new namespace called System.Addin which allows us to create AddIns for our applications.

What Are AddIns

AddIns (sometimes called Plugins) are seperately compiled components that an application can locate, load and make use of at runtime (dynamically). An application that has been designed to use AddIns can be enhanced (by developing more AddIns) without the need for the orginal application to be modified or recompiled and tested (though the AddIns should be tested). For some time .NET has allows developers to create applications that use AddIns but this more than likely used the System.Reflection namespace, and was probably a fair bit of work. With .NET 3.5 comes a new namespace, namely the System.Addin namespace. The .NET team have created a very flexible framework for building AddIns, this is known as the AddIn Pipeline (System.AddIn.Pipeline). By using the AddIn Pipeline, the neseccary plumbing is already in place to allow the AddIn model to work. So thats a good thing. The down side to this is that you must implement at least 7 different components to implement the most basic AddIn model. The next section will discuss the AddIn pipeline concept (though it will not discuss the System.AddIn.Pipeline namespace) and shall discuss what happens in each of the 7 (minimum) components that are required in order to correctly setup a AddIn model enabled application

The AddIn Pipeline

The heart of the Addin model is the pipeline. The pipeline is a chain of components that allows the application to communicate with the AddIn. At one end of the pipeline is the Host Application and at the other end is the AddIn, and in between are 5 other components that facilitate the AddIn operation and interaction. Consider the following Diagram At the center of this figure is the Contract (implements System.AddIn.Contract.IContract), which includes one or more interfaces that define how the host application and the AddIns can interact. The Contract can also include serializable types that are planned to between the host application and the AddIn. Microsoft designed the AddIn model with extensibility in mind, as such both the host application and the actual AddIn dont actually use the Contract directly, rather they use their own respective versions of the Contract, called Views. The host application uses the host view, while the AddIn uses the AddIn view. The views normally contain an abstract class that reflect the interfaces in Contract interface (though the view dont inherit from the Contract or implement the System.AddIn.Contract.IContract interface). If this perks your interest I have written a full article complete with a demo project which is available over at codeproject. Or if you just want the demo project without reading the article you can simply use this link demo project.zip