WCF

WCF Tips

As a result of messing around with WCF lately, I have just compiled a list of a few tips which I am bundled into an article which you can find over at codeproject using the following link

http://www.codeproject.com/KB/WCF/WCFTips.aspx

Advertisements
C#, CodeProject, LINQ

Reading Feeds with XLINQ

I have done a number of projects that all parse RSS Feeds using XLINQ. Which in itself is awesome, and much easier than using old XML techniques. Where I would so something like

   1:  public static List<PhotoInfo> LoadLatestPictures()
   2:  {
   3:   try
   4:   {
   5:     var xraw = XElement.Load(MOST_RECENT);
   6:     var xroot = XElement.Parse(xraw.ToString());
   7:     var photos = (from photo in xroot.Element("photos").
   8:     Elements("photo")
   9:      select new PhotoInfo
  10:      {
  11:        ImageUrl =
  12:        string.Format(
  13:        "http://farm{0}.static.flickr.com/{1}/{2}_{3}_m.jpg",
  14:        (string)photo.Attribute("farm"),
  15:        (string)photo.Attribute("server"),
  16:        (string)photo.Attribute("id"),
  17:        (string)photo.Attribute("secret"))
  18:      }).Take(Constants.ROWS * Constants.COLUMNS);
  19:              return photos.ToList<PhotoInfo>();
  20:    }
  21:    catch (Exception e)
  22:    {
  23:      Trace.WriteLine(e.Message, "ERROR");
  24:    }
  25:    return null;
  26:  }

.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; } .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; }However today I found something even cooler.

Have a look at the code below.

   1:  using System.ServiceModel.Syndication;
   2:  using System.Xml;
   3:  using System.IO;
   4:  using System.Xml.Linq;
   5:  
   6:  public class DataService : IDataService
   7:  {
   8:      public SyndicationFeedFormatter GetGeoRSS()
   9:      {
  10:          var geoRss =
  11:          @"<?xml version='1.0' encoding='utf-8' ?>
  12:              <rss version='2.0'
  13:                  xmlns:geo='http://www.w3.org/2003/01/geo/wgs84_pos#'
  14:                  xmlns:georss='http://www.georss.org/georss'
  15:                  xmlns:gml='http://www.opengis.net/gml'
  16:                  xmlns:mappoint='http://virtualearth.msn.com/apis/annotate#'>
  17:                <channel>
  18:                  <title>Mount Saint Helens - Mount Margaret Trail</title>
  19:                  <link></link>
  20:                  <description>Trailheads and campsites in the Mount
  21:                  Margaret area of
  22:                  Mount Saint Helens, WA</description>
  23:                  <mappointIntlCode>cht</mappointIntlCode>
  24:                  <item>
  25:                    <title>Coldwater Lake</title>
  26:                    <description>Formed by the 1980 eruption of
  27:                      Mount St. Helens.</description>
  28:                    <georss:polygon>46.31409 -122.22616 46.31113
  29:                      -122.22968 46.31083 -122.23320 46.29802
  30:                      -122.25877 46.29245 -122.26641 46.29286 -122.26392
  31:                      46.28746 -122.26744 46.28741 -122.26006
  32:                      46.29049 -122.25955 46.29120 -122.25620
  33:                      46.28924 -122.255430 46.30271 -122.23251
  34:                      46.31284 -122.22315
  35:                      46.31409 -122.22616</georss:polygon>
  36:                    <icon>http://dev.live.com/virtualearth/sdk/
  37:                      img/hiking_icon.gif</icon>
  38:                  </item>
  39:                  <item>
  40:                    <title>Lakes Trailhead</title>
  41:                    <description>This is where we started our hike,
  42:                      just down the road from the visitor center.
  43:                      You could also start at the visitor center.
  44:                  </description>
  45:                    <geo:lat>46.2913246</geo:lat>
  46:                    <geo:long>-122.2658157</geo:long>
  47:                  </item>
  48:                </channel>
  49:              </rss>";
  50:  
  51:          var xDoc = XDocument.Parse(geoRss);
  52:          var feed = SyndicationFeed.Load(xDoc.CreateReader());
  53:  
  54:          Rss20FeedFormatter feed2 = Rss20FeedFormatter(feed);
  55:          return feed2;
  56:      }
  57:  }

.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; } .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; }

The thing to note here is the “SyndicationFeed” and “Rss20FeedFormatter” classes. How cool is that.

So when you a  Rss20FeedFormatter object, you get properties to get straight to all the usual RSS things you would like to use, such as Feed.Items

image

This is very cool. I am constantly being surprised by just what .NET can do, it just goes to show you need to keep an eye on the namespaces. There are new ones in there all the time.

System.ServiceModel.Syndication Huh, well I’ll be.

WPF

MarsaX

Some time ago a colleague of mine showed me a web browser addin called PicLens, that did some very funky 3D visualization of searched results.

 

image

 

I got quite jealous about this and had a think about it and set to work trying to give it a go in WPF. I think I actually got pretty close to the PicLens version and the only areas where I think it could be improved are in the following areas:

  • Virtualization, such that item out of view are removed from the 3D viewport
  • Video support, though I did figure a way to get YouTube videos into WPF using a WebBrowser component. Unfortunately the WebBrowser component is a Window based HWnd control, so doesn’t work like other WPF controls, and as such was unsuitable for being hosted in a 3D viewport.

 

Here is a screen shot of MarsaX running.

 

image

 

image

 

image

 

Ill just give you a brief run down of how it all hangs together

 

  1. The top right hand buttons use a StoryBoard to show a hidden search area panel.
  2. The search area panel contains buttons, which allow the user to search RSS feeds using XLINQ, which are read in asynchronously using a ThreadPool
  3. The search results are then used to create a new 3D item which is put into a 3D container
  4. The bottom control is a simple Slider control which has been Styled to look like this. When you move the slider the 3D container is animated around an angle and distance
  5. There is another Styled slider which can be used to zoom in/out of the 3D scene
  6. When a 3D item is clicked on it shows a popup window from where the user may save the image
  7. The application uses various different configuration items to control how it works

 

I did get some help with this article from a fellow geek called Marlon Grech whom I think is a uber smart kid. Marlon wrote some of the Styles that the control use and helped with some code areas.

All in all both Marlon and I were pretty happy with the results of this article.

 

Go check it out at the MarsaX link over at Codeproject

http://www.codeproject.com/KB/WPF/MarsaX.aspx

CodeProject, WPF

WPF Localization

recently at work I was asked to look into Localization techniques when working with WPF/XAML. There are some excellent sources around that cover the various different techniques such as

this excellent article which outlines the following techniques

Using Locbaml

Locbaml is a localization tool that Microsoft have as a free download, available from http://msdn.microsoft.com/en-us/library/ms771568.aspx. This tool may be used to translate compiled XAML (binary XAML, BAML) resources into a CSV and may be used to translate a CSV file into a new Dll.

Here are the steps involved with doing this

1. Create normal WPF App, and use a ResourceDictionary for strings

2. Use MergedDictionary in App.resources

3. Add [assembly: NeutralResourcesLanguage(“en-US”, UltimateResourceFallbackLocation.Satellite)] in AssemblyInfo.cs

4. Add new <UICulture>en-US</UICulture> in all ProjectGroup tags for current project

5. Open command prompt at project level, run msbuild /t:updateuid <PROJECT NAME>.csproj

6. Open command prompt at project level, run msbuild /t:checkuid <PROJECT NAME>.csproj

7. Build it from VS

8. Obtain 1st cultures CSV file, LocBaml.exe /parse en-US/<PROJECT NAME>.resources.dll /out:<PROJECT NAME>.csv

9. Edit CSV save as new csv file name, such as <PROJECT NAME><nn-XX CULTURE STRING>.csv

10. Need to do translation for new culture. Do something like

11. LocBaml.exe /generate en-US/HelloWorld.resources.dll /trans :HelloWorldfr-CA.csv /out:c: /cul:fr-CA

12. Create new <nn-XX CULTURE STRING> directory in Bin folder

13. Copy <PROJECT NAME>.resources.dll from step 10, which was placed on C: to the folder created in step 11

14. Create a constructor for App class like follows:

public App()

{

string culture = “fr-CA”; //Where this is the culture you want to use

System.Threading.Thread.CurrentThread.CurrentUICulture =

new System.Globalization.CultureInfo(culture);

System.Threading.Thread.CurrentThread.CurrentCulture =

new System.Globalization.CultureInfo(culture);

}

Advantages Of This Method

  • You can do it at the end of the project
  • You don’t have to interfere with your main Assembly to install new cultures

Disadvantages Of This Method

· It is laborious and error prone

· Not well suited for teams of developers as a new CSV file is created each time you use the LocBaml tool, so you need to know what was different between newly exported CSV file and the translation CSV file

Using RESX Files

An alternative approach is to not use Locbaml at all and simply use RESX (resource files).

Here are the steps involved with doing this

  1. Create normal WPF App
  2. There will already be a resx file within the Properties folder, so simply add a string value to that for the text you want to localize. Make sure to select public from Access Modifier drop down
  3. Within any Window that you want to use localized text, add a clr-namespace such as
  4. xmlns:properties=”clr-namespace:HelloWorldUsingResXFiles.Properties”
  5. Hook up a items text to a resource file text, like
  6. <Button Margin=”10″ Name=”button1″
  7. Content=”{x:Static properties:Resources.MainButtonText}”></Button>
  8. Copy and paste the existing resx file within the Properties folder to a new file with the following name
  9. Resources.<nn-XX CULTURE STRING>.resx
  10. Modify the App.cs file to include whatever culture should be used, for example

public App()

{

HelloWorldUsingResXFiles.Properties.Resources.Culture = new CultureInfo(“fr-CA”);

}

Advantages Of This Method

  • Very easy to implement

Disadvantages Of This Method

· All RESX files must be stored in Main Assembly

· As all cultural resource files are in Main Assembly, may make doing automated build harder

Another Way : Use Dynamically Loaded Assemblies With ResourceDictionaries

I just couldn’t help but think there was a better way, so I had a think about this, and it seems just like the way skins are applied in WPF. You wire certain control properties to DynamicResources where a new XAML file (the skin) is loaded which effects the control that is referencing the resource. So I had a think about it and thought why not do the same for Localization strings. So that’s what I did. Here is the idea

Keep a Main Assembly which expects to get localization resources from a ResourceDictionary, and then at runtime load in an extra Assembly which contains just the ResourceDictionaries for the matching CurrentCulture where the application is running.

The loaded Assemblies ResourceDictionaries will be used to replace the default one within the main Assembly.

1. Create normal WPF App, and use a ResourceDictionary for strings

2. Use MergedDictionary in App.resources

3. Make sure any localizable controls using a DynamicResource like

<Label Content=”{DynamicResource label1}”/>

4. Create a new culture assembly with a sensible name, such as Culture_fr-CA

5. For assembly created in step 4, create mirror image ResourceDictionary that matches the original Assemblies ResourceDictionary. but with translated strings

6. Compile the culture assembly to some folder under main Assemblies bindebug folder. This demo assumes this folder is called “CultureFiles”

7. When main app runs, get current culture and Load the matching Assembly from disk

8. From the currently loaded Culture Assembly, extract the ResourceDictionary

9. Using the extracted ResourceDictionary, replace the current Application.MergedResources dictionary with the newly extracted culture ResourceDictionary

10. All controls that refer to the Dynamic resources should be ok now with new cultural strings

In my main App I simply have the following ResourceDictionary

   1:  <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   2:      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   3:      xmlns:system="clr-namespace:System;assembly=mscorlib">
   4:      <system:String x:Key="label1">label1</system:String>
   5:      <system:String x:Key="label2">label2</system:String>
   6:      <system:String x:Key="label3">label3</system:String>
   7:      <system:String x:Key="label4">label4</system:String>
   8:      <system:String x:Key="label5">label5</system:String>
   9:  </ResourceDictionary>

.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; }

Then in the App file I have the following

   1:  <Application x:Class="LooseXAML.App"
   2:      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:      StartupUri="Window1.xaml">
   5:  
   6:      <Application.Resources>
   7:          <ResourceDictionary>
   8:              <ResourceDictionary.MergedDictionaries>
   9:                  <ResourceDictionary Source="Dictionary_en-US.xaml" />
  10:              </ResourceDictionary.MergedDictionaries>
  11:          </ResourceDictionary>
  12:      </Application.Resources>
  13:  
  14:  </Application>

.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; }

Then somewhere I may reference these resources like

   1:  <Label Content="{DynamicResource label1}"/>

.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; }

So that is all pretty standard stuff. Next I created a new Assembly with a single ResourceDictionary in it. I am using the culture string as part of the Assembly name and or the actual ResourceDictionary

image

The actual ResourceDictionary MUST contain the name items as the main Assembly

   1:  <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   2:      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   3:      xmlns:system="clr-namespace:System;assembly=mscorlib">
   4:      <system:String x:Key="label1">french label1</system:String>
   5:      <system:String x:Key="label2">french label2</system:String>
   6:      <system:String x:Key="label3">french label3</system:String>
   7:      <system:String x:Key="label4">french label4</system:String>
   8:      <system:String x:Key="label5">french label5</system:String>
   9:  </ResourceDictionary>

.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; }

From here I compile this assembly and put it somewhere visible from the main Assembly, such as bindebugCultureFiles

image

From there is just a question of loading the seperate culture Assemblies and extracting the contained ResourceDictionary and replacing the current Main Assemblies ResourceDictionary. Thus forcing all resourced referencing controls to update with the new resource data.

There is a small demo application that demonstrated this approach here which you may test by clicking on the the fr-CA listbox item

Before

image

After

image

But you MUST ensure that your current culture is set to French-CANADA via control panel for it to work. This means change region Options AND languages. If you don’t do this the CurrentCulture will not be correct for the demo code to work.

image

Advantages Of This Method

  • Very easy to implement

Disadvantages Of This Method

· Lots of different Assemblies to manage

· Culture Assemblies ResourceDictionary entries must match Main Assembly otherwise a lookup may fail at runtime

Beginners Guide To Threading

Another Threading Article Is Out (Part2)

As some of you may know I have embarked on a mission to write some articles over at codeproject about threading. Part 2 of this crusade is now available using this link. In this one I talk about how to control Thread state, and also some common threading traps. I hope you enjoy it. It has been critiqued a little, for being a little MSDN like, so Ill try and come up with a different angle on the next article so that there is something different for you to read.

Introduction

WPF GlassEffect For Non Vista OS

For those of us fortunate enough to own Windows Vista we can now see transparent windows that show the content behind our window through a glass window. This is down to the Desktop Windows Manager ability to extend the glass effect into the client area. This is however only possible on Windows Vista.

I had a little play around with WPF today and came up with a very crude (no resize window support) example for non Vista Windows versions that can run WPF. As I say its very crude but gives you the basic idea.

The idea is that you set the Window mode to AllowTransparency and set the WindowStyle to None, and then within any Glass enabled window you use some boiler plate code which mimics the Vista glass effect.

This is done via the use of a Canvas layout control. As Canvas allows objects to be placed using different ZIndex, you can create an overall semi-transparent area (the Glass) and then lay your controls on top of that. The only down side is that as canvas is an X/Y layout manager you will probably have to do at least 1 piece of code that makes sure the actual content is given the correct size you want.

 

Lets see the code, first the XAML

 .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; }
   1:  <Window x:Class="GlassWindowForXP.Window1"
   2:      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
   4:      Background="Transparent"
   5:      Title="Window1" Height="600" Width="800"
   6:      x:Name="Window">
   7:      <Canvas x:Name="canvmain">
   8:   
   9:          <Canvas.Resources>
  10:   
  11:              <ControlTemplate x:Key="imageButton" 
  12:                               TargetType="{x:Type Button}">
  13:                  <Image Source="{Binding 
  14:                      RelativeSource={RelativeSource TemplatedParent},
  15:                   Path=Tag}" Width="{TemplateBinding Width}"
  16:                         Height="{TemplateBinding Height}" 
  17:                         Stretch="Fill"/>
  18:              </ControlTemplate>
  19:   
  20:          </Canvas.Resources>
  21:   
  22:          <Rectangle Opacity="0.800000" x:Name="back"
  23:                     Width="{Binding ElementName=canvmain, 
  24:                      Path=ActualWidth}" 
  25:                     Height="{Binding ElementName=canvmain, 
  26:                      Path=ActualHeight}" 
  27:                     StrokeThickness="2.000000" Stroke="#55505050" 
  28:                     StrokeMiterLimit="1.000000">
  29:              <Rectangle.Fill>
  30:                  <LinearGradientBrush StartPoint="0.499999,0.019669" 
  31:                                       EndPoint="0.499999,0.957376">
  32:                      <LinearGradientBrush.GradientStops>
  33:                          <GradientStop Offset="0.000000" 
  34:                                        Color="#ffe8e8e8"/>
  35:                          <GradientStop Offset="1.000000" 
  36:                                        Color="#ffbababa"/>
  37:                      </LinearGradientBrush.GradientStops>
  38:                  </LinearGradientBrush>
  39:              </Rectangle.Fill>
  40:          </Rectangle>
  41:   
  42:          <DockPanel Margin="0" Background="Transparent" LastChildFill="True">
  43:              <DockPanel DockPanel.Dock="Top" Background="RoyalBlue" 
  44:                         Width="{Binding ElementName=canvmain, Path=ActualWidth}" >
  45:                  <Label x:Name="lblTitle" DockPanel.Dock="Left" 
  46:                         Content="{Binding Path=Title, ElementName=Window, 
  47:                          Mode=Default}" 
  48:                         VerticalAlignment="Center" FontFamily="Arial Rounded MT" 
  49:                         FontSize="12" FontWeight="Bold" Foreground="#FFFFFFFF" />
  50:                  <StackPanel DockPanel.Dock="Right" Height="30" Width="75" 
  51:                              Orientation="Horizontal" HorizontalAlignment="Right"  >
  52:                      <Button x:Name="btnMin" Width="21" Height="21" Margin="2" 
  53:                              Template="{StaticResource imageButton}" Tag="images/minimise.png" 
  54:                              HorizontalAlignment="Right" Click="btnMin_Click" 
  55:                              VerticalAlignment="Center"/>
  56:                      <Button x:Name="btnMax" Width="21" Height="21" Margin="2" 
  57:                              Template="{StaticResource imageButton}" Tag="images/maximise.png" 
  58:                              HorizontalAlignment="Right" Click="btnMax_Click" 
  59:                              VerticalAlignment="Center"/>
  60:                      <Button x:Name="btnClose" Width="21" Height="21" Margin="2" 
  61:                              Template="{StaticResource imageButton}" Tag="images/close.png" 
  62:                              HorizontalAlignment="Right" Click="btnClose_Click" 
  63:                              VerticalAlignment="Center"/>
  64:                  </StackPanel>
  65:              </DockPanel>
  66:   
  67:              <TabControl Margin="20" Height="400">
  68:                  <TabItem Header="TabItem">
  69:                      <Grid/>
  70:                  </TabItem>
  71:                  <TabItem Header="TabItem">
  72:                      <Grid/>
  73:                  </TabItem>
  74:              </TabControl>
  75:          </DockPanel>
  76:      </Canvas>
  77:  </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 C# code for it

   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 GlassWindowForXP
  16:  {
  17:      /// <summary>
  18:      /// Interaction logic for Window1.xaml
  19:      /// </summary>
  20:      public partial class Window1 : Window
  21:      {
  22:          public Window1()
  23:          {
  24:   
  25:              this.WindowStyle = WindowStyle.None;
  26:              this.AllowsTransparency = true;
  27:              this.Background = new 
  28:                  SolidColorBrush(Color.FromArgb(0, 34, 34, 34));
  29:              InitializeComponent();
  30:          }
  31:   
  32:          protected override void 
  33:              OnMouseLeftButtonDown(MouseButtonEventArgs e)
  34:          {
  35:              base.OnMouseLeftButtonDown(e);
  36:              this.DragMove();
  37:          }
  38:   
  39:          private void btnClose_Click(object sender, RoutedEventArgs e)
  40:          {
  41:              this.Close();
  42:          }
  43:   
  44:          private void btnMin_Click(object sender, RoutedEventArgs e)
  45:          {
  46:              this.WindowState = WindowState.Minimized;
  47:          }
  48:   
  49:          private void btnMax_Click(object sender, RoutedEventArgs e)
  50:          {
  51:              this.WindowState = WindowState.Maximized;
  52:          }
  53:      }
  54:  }

.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 what it looks like running

image

 

And here is a link to the source code glasswindowforxp.zip as I say this is very crude, and wouldn’t be suitable for production code the way it is, but it gives you a starting point

CodeProject, WPF

A Moan About ImageBrush In WPF

I am working on a 3D article in WPF, and I wanted to use an ImageBrush but was having some issues with it, so I decided to split this out into a small test app.

I had the following setup

image

And I simply wanted to test this out by creating an ImageBrush that I could use to say change the Background of a Button. So I had the following code

   1:              //THIS DOESNT WORK UNLESS I UNCOMMENT THE CODE BELOW, 
   2:              //WHICH IS NOT EVEN RELATED
   3:              System.Windows.Media.ImageBrush brush =
   4:                  new System.Windows.Media.ImageBrush();
   5:              BitmapImage img = new BitmapImage(
   6:                  new Uri(@"images/image1.jpg", UriKind.RelativeOrAbsolute));
   7:              brush.ImageSource = img;
   8:              btnImage.Background = brush;

.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; }

 

.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; }Now I thought this should work. Yet when I ran it I got

image

So I then tried to add an image to the code so we now had

   1:  <Window x:Class="ImageBrush.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:      <StackPanel x:Name="sp1">
   6:          <Button x:Name="btnImage" Margin="10" Height="60"/>
   7:      </StackPanel>
   8:  </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; }
.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 code behind

   1:              //THIS DOESNT WORK UNLESS I UNCOMMENT THE CODE BELOW, 
   2:              //WHICH IS NOT EVEN RELATED
   3:              System.Windows.Media.ImageBrush brush =
   4:                  new System.Windows.Media.ImageBrush();
   5:              BitmapImage img = new BitmapImage(
   6:                  new Uri(@"images/image1.jpg", UriKind.RelativeOrAbsolute));
   7:              brush.ImageSource = img;
   8:              btnImage.Background = brush;
   9:  
  10:  
  11:              //BUT IF I UNCOMMENT THESE THE ABOVE CODE WORKS JUST FINE
  12:              Image img2 = new Image();
  13:              img2.Source = img;
  14:              sp1.Children.Add(img2);

.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; }

 

 

.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; }This seemed to work for me. But I didn’t want an Image, so that was out. I figured this has to be some trick that Image can do that ImageBrush cant. For ImageBrush I imagined that I needed to read from the Assembly resources. So I had a hunt about and found the  following code over at Tamir Khasons blog.

image

Which allows us to do things like

image

or for framework elements

image

All of which is way coo. But it still didn’t sit right with me, so I asked my mate Josh Smith about this and he simply suggested changing the Build Action of the image to “Content”. This did the trick, the spectacular results of which are shown here

image

Brilliant hey. But beware, when we set a Build Action to “Content”, You also lose the ability to localize that image. (Images built with a Resource build action are loaded via a ResourceManager, which means they can be substituted with images in localized satellite resource assemblies.)

From here on this blog will be using some information that has been the result of a chat with Ian Griffiths.

In fact it’s perfectly possible to use a compiled in resource in an ImageBrush, you just need a more specific URI, so we could then use a url like the following

image

Where we use a fully-qualified pack URI. I called my test application ImageBrushAsResource by the way – obviously you’d need to put your component’s name there in its place.

We can actually use a Relative path in XAML though for an Image such as

image

It’s using ImageSourceConverter to convert that text string into an ImageSource, and the process that uses isn’t quite the same as the process you’ve used in your code. The Xaml parser will pass the ImageSourceConverter a context object that offers an IUriContext service, letting it discover the base URI of the containing Xaml document, and it resolves the URI relative to that. So it corresponds to this:

image

This lets you use a relative URI, as in the original example. It converts it into a full URI using your Window’s base URI, which will be something like “pack://application:,,,/ImageBrush;component/window1.xaml” so it ends up resolving your relative URI to the same fully-qualified URI that my first example uses. But the advantage here is that you don’t need to hard code that into your codebehind. You just ask WPF what the base URI should be.

So by using either of these methods in code behind you are able to do without Tamir’s code.

  • Use Build Action of Resource, and use full Pack Uri
  • Use Build Action of Resource, and use BaseUriHelper

All in all a rather interesting post, I feel.