Where did my StartupPath go?
So somebody has just asked where Application.StartupPath has disappeared in WPF. This is available in Windows Forms, but not available in WPF. A common technique to get the startup path is to use Assembly.GetEntryAssembly().Location, but there’s a problem with GetEntryAssembly if your app is fired off from an unmanaged application, such as a COM application for instance.
We have a couple of applications where our executable is fired off as a result of unmanaged processing – primarily when processing image data that’s been collected and checkpointed by some native code. We’ve found that GetEntryAssembly is null in this instance, whereas the following method works fine.Now one way that you could add this in would be to add a reference to System.Windows.Forms into your project and then call it from there – however, there’s a way that you can do it without needing to go anywhere near WinForms just by adding a few lines of code. Here it is – in all its glory.
public static class Utility
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetModuleFileName(HandleRef hModule, StringBuilder buffer, int length);
private static string startupPath;
private static HandleRef NullHandleRef = new HandleRef();
public static string StartupPath()
{
if (startupPath == null)
{
StringBuilder buffer = new StringBuilder(260);
GetModuleFileName(NullHandleRef, buffer, buffer.Capacity);
startupPath = Path.GetDirectoryName(buffer.ToString());
}
new FileIOPermission(FileIOPermissionAccess.PathDiscovery, startupPath).Demand();
return startupPath;
}
}
As you can see, the code merely wraps up a call to GetModuleFileName, it’s that simple.
Note – since posting this, one of my fellow WPF Disciples handed over the following code which should work as well:
startupPath = (Assembly.GetEntryAssembly() ?? Assembly.GetExecutingAssembly()).Location
Fun with fonts
So I’ve been playing around with the RichTextBox for WPF and decided that it would be a great idea to add font selection to the code. Obviously, this being WPF, I didn’t want to just list the fonts out, I wanted to list the fonts out in exactly the way they’d be displayed. In other words, I want the font name to be written out using the font itself. By now it shouldn’t come as a surprise to you that this is extremely easy to do in WPF.
First of all, it’s really easy to get a list of the fonts. .NET provides a handy little class cunningly enough known as InstalledFontCollection, so we’ll wrap that up in a handy list ready for use:
using System;
using System.Collections.Generic;
using System.Drawing.Text;
using System.Drawing;
namespace FontManager
{
public class InstalledFonts : List<FontFamily>
{
public InstalledFonts()
{
InstalledFontCollection fonts = new InstalledFontCollection();
this.AddRange(fonts.Families);
}
}
}
This class just wraps up the installed font families into a handy dataprovider format. This is all about being nice and blend-friendly.
Next we want to define a usercontrol to display the fonts. Something to note about this control; we display the data in a virtualizing stack panel – if you don’t, you could end up waiting quite a while for the first display of the font.
<UserControl
x:Class="FontManager.InstalledFontDisplay"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:drawing="clr-namespace:System.Drawing;assembly=System.Drawing"
xmlns:m="clr-namespace:FontManager"
xmlns:sys="clr-namespace:System.Collections.Generic;assembly=mscorlib"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<UserControl.Resources>
<Style x:Key="FontStyle">
<Setter Property="Control.FontFamily" Value="{Binding Name}" />
<Setter Property="Control.FontSize" Value="16" />
</Style>
<DataTemplate x:Key="FontTemplate">
<StackPanel VirtualizingStackPanel.IsVirtualizing="True">
<TextBlock
Text="{Binding Name}"
ToolTip="{Binding Name}"
Style="{StaticResource FontStyle}" />
</StackPanel>
</DataTemplate>
<ObjectDataProvider x:Key="FontProvider" ObjectType="{x:Type m:InstalledFonts}"/>
</UserControl.Resources>
<ComboBox
VerticalAlignment="Top"
ItemsSource="{Binding Source={StaticResource FontProvider}}"
ItemTemplate="{StaticResource FontTemplate}" />
</UserControl>
That’s it – that’s all there is to displaying your font names in the appropriate font. It is so easy, and yet another reason to love WPF. Go on – you know you love it.
Onyx
So, there’s this guy called Bill Kempf who’s a fellow WPF Disciple. Now, Bill’s an extremely smart guy who’s come up with a framework that helps ease the pain when developing MVVM applications. If you are serious about developing robust WPF and Silverlight applications, then I can heartily recommend that you take a look at the Onyx framework.
MoXAML 2.4 Released
I’ve just uploaded the newest version of MoXAML Power Toys. MoXAML now includes a version of Scrubber that runs inside Visual Studio – Scrubber was introduced to the world by Robby Ingebretsen in his wonderful Kaxaml tool. Go on – beautify all the XAML in your projects with one simple menu option.
Binding to a single object.
So today, on CodeProject, one of the WPF regulars posed a question about whether or not you could only bind to ObservableCollection objects, and if you could bind to single objects, how could you guarantee two way databinding goodness. As you may well imagine, I promptly answered that you could indeed bind to a single object and implement two way databinding with it. The discussion also posed the question, could WPF bind to properties that linked into child objects and display these – from separate usercontrols.
This seemed to me to be an ideal candidate for demonstrating the beauty and wonder that is the WPF databinding infrastructure. If you’ve only ever been exposed to WinForms or ASP.NET databinding, then you are in for a major treat – WPF (and Silverlight) provide so much more bang for your buck with binding that it’s hard to see how we managed before. First of all, let’s take a look at our business object classes, Benefit and Customer. Both of these classes implement INotifyPropertyChanged so that we get access to the notification mechanism that supports two way binding.
First of all, here’s Benefit.cs:
As you can see, there’s nothing out of the ordinary in these classes – they don’t do anything clever. They are just your bog standard, basic model classes.
Now, here’s the main window XAML:
The TextBoxes are bound to the relevant entries in the Customer class using the familiar {Binding Path=…} syntax. But wait, where’s the Benefit class in all this? I added it for a reason, yet there’s no sign of it. Well, as you can see – there’s a reference to a UserControl (BenefitsControl), and we are going to perform the actual binding in this class. Here’s the definition of BenefitsControl.xaml:
Look – there’s the binding Benefits.ProviderName, but would it surprise you to know that I’m not going to put the data class anywhere near this control. I’m going to set the DataContext on the parent control and let the usercontrol “find” the data there. Here’s the implementation of the code behind the parent XAML (Window1.cs):
So - here’s the application in all its glory:
Well – now that we’ve covered the code, how does the databinding actually work? How does the user control actually get its binding to work? This is where the wonder that is WPF actually comes into play. If the binding can’t find data in the data context at the current level, it works its way back up the logical tree until it can. Seriously – I love this stuff, and I’d hate to go back from it.
The code for this application can be downloaded here. Note that you’ll need to change the extension from .doc to .zip.
Action based ViewModel and Model validation.
A while ago, WPF guru Josh Smith blogged about using the ViewModel to provide a first line of defence when validating data using the MVVM model. In his article, Josh talks about having the ViewModel perform some validation before passing this back to the underlying model. In his example, he uses a string property to perform initial validation on a UI element before it updates an integer, so that the user can type in abc123, but the model only gets updated if it’s a valid number. Please read his article here for more information.
While I liked Josh’s implementation, there was something nagging at me – his implementation relied heavily on switch statements in the property validation, and this really goes against the grain for me. Thinking about this for a while, it seemed to me that we could achieve a similar implementation and, at the same time, provide a nice level of abstraction. To do this, we can use the Action<T> delegate to nicely decouple the validation from the actual property validation. The following class provides the underlying mechanism for separating the validation.
Now, both the ViewModel and Model classes can derive from this class and get access to the same functionality. The following class demonstrates this:
The interesting bit of this class is how simple the implementation of IDataErrorInfo here actually is. All the “magic” has been taken care of by creating an Action that will invoke the ValidateAge method. By calling AddValidation on the base class and passing the name of the property that the validation applies to, we can automatically hook up to perform the validation.
You can download the sample project here. Be sure to change the extension back from Doc to Zip and then decompress it.
A CodeProject MVP again.
My good friend, Mr Karl Shifflett, just let me know that I’ve been awarded CodeProject MVP status for a second year. I’m so proud, and it’s good to see that so much ground has been made up of the WPF Disciples here.
Thanks to Chris and the CP community – it’s been a blast guys and gals.
Sci Fi collector shop.
Our daughters are huge Dr Who fans, so it was only natural that we would look for a Dr Who toy for them for Christmas. Well, Hannah (our 4 year old) thinks the Adipose are wonderful. For those who don’t know, the Adipose were a creature from the last series who were made up of fat. They looked cute and Hannah nicknamed them cutibles. So, we were going to buy a soft toy Adipose for Hannah but you couldn’t find them for love or money.
Well – to cut a long story short, this site (http://www.scificollector.co.uk/) had them in stock and their customer service and helpfulness is wonderful. If you are looking for Sci Fi merchandise, you owe it to yourself to stop on by.
Watermarked TextBox
Well, I love mucking around in code and I recently decided to see how easy it would be to knock together a user control that would work in both WPF and Silverlight. If you keep it simple, it is really really easy to do. To this end, I present to you the WatermarkTextbox.
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel;
{
public class WatermarkTextBox : TextBox, INotifyPropertyChanged
{
public WatermarkTextBox()
{
ApplyWatermark();
}
protected virtual void Changed(string propertyName)
{
ApplyWatermark();
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
private string _watermarkText = “Watermark”;
public string WatermarkText
{
get
{
return _watermarkText;
}
set
{
if (_watermarkText != value)
{
if (string.IsNullOrEmpty(Text) || Text == _watermarkText)
{
Text = value;
}
_watermarkText = value;
Changed(“WatermarkText”
}
}
}
private System.Windows.Media.Brush _watermarkForeground = new SolidColorBrush(Colors.LightGray);
public System.Windows.Media.Brush WatermarkForeground
{
get
{
return _watermarkForeground;
}
set
{
if (_watermarkForeground != value)
{
_watermarkForeground = value;
Changed(“WatermarkForeground”
}
}
}
private System.Windows.Media.Brush _watermarkBackground = new SolidColorBrush(Colors.Yellow);
public System.Windows.Media.Brush WatermarkBackground
{
get
{
return _watermarkBackground;
}
set
{
if (_watermarkBackground != value)
{
_watermarkBackground = value;
Changed(“WatermarkBackground”
}
}
}
private System.Windows.Media.Brush _standardForeground = new SolidColorBrush(Colors.Black);
public System.Windows.Media.Brush StandardForeground
{
get
{
return _standardForeground;
}
set
{
if (_standardForeground != value)
{
_standardForeground = value;
Changed(“StandardForeground”
}
}
}
private System.Windows.Media.Brush _standardBackground = new SolidColorBrush(Colors.White);
public System.Windows.Media.Brush StandardBackground
{
get
{
return _standardBackground;
}
set
{
if (_standardBackground != value)
{
_standardBackground = value;
Changed(“StandardBackground”);
}
}
private void
{
Foreground = StandardForeground;
Background = StandardBackground;
}
protected override void OnGotFocus(RoutedEventArgs e)
{
if (Text == WatermarkText)
{
Text = string.Empty;
SetStandard();
}
base
}
protected override void OnLostFocus(RoutedEventArgs e)
{
Text = Text.Trim();
if (Text.Length == 0)
{
ApplyWatermark();
}
base
}
private void ApplyWatermark()
{
if (string.IsNullOrEmpty(Text) || Text == WatermarkText)
{
Text = WatermarkText;
Foreground = WatermarkForeground;
Background = WatermarkBackground;
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
}
Please feel free to use this class as you like. It comes with no warranty because it’s intended as a proof of concept only. It can do with a tidy up, and it should use Coerce values but I leave that for you to do.
MoXAML 2.2 Released
Well – MoXAML 2.2 has been released, with a new Create Dependency Property command.
The Create Dependency Property command lets you create an ordinary DP or Attached DP (or readonly versions) with a minimum of effort. Better still, it provides method implementations for you as well.
Selecting the menu (from inside the code editor window) brings up a dialog to enter the core information that you need to create the DP. When you enter the default value, you need to put it in “exactly” as you would if you entered it manually. This means that you must put quotes around it if that’s what is expected by the datatype.
The Create Dependency Property window
When you choose Create, the relevant code gets added into the class.













