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
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
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
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.
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.
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:
Here is a screen shot of MarsaX running.
Ill just give you a brief run down of how it all hangs together
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
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
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
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
An alternative approach is to not use Locbaml at all and simply use RESX (resource files).
Here are the steps involved with doing this
public App()
{
HelloWorldUsingResXFiles.Properties.Resources.Culture = new CultureInfo(“fr-CA”);
}
Advantages Of This Method
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
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
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
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
After
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.
Advantages Of This Method
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
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.
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
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
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
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
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 RELATED3: 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 FINE12: 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.
Which allows us to do things like
or for framework elements
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
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
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
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:
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.
All in all a rather interesting post, I feel.