Tigraine

Daniel Hoelbling-Inzko talks about programming

Theming controls in WPF

My biggest grief with WPF is the way how twisted XAML works. It takes a lot of time getting used to it, and it’s by no means obvious how to do stuff.

So this is the story of how to change the appearance of a control from some common resource for controls.

Styles and Setters

Most of the things you’d consider styling (as known from CSS) can be done via Styles that contain setters.

Inside a ResourceDictionary you can define styles for all controls of a type, or have them be applicable by a key. This is pretty similar to CSS where you can apply settings either via class (by key in WPF) or by elementType (TargetType in WPF)

Let’s look at some code:

.highlight {
	color: Red;
} 

translates into the following XAML:

<Style x:Key="highlight"> <Setter Property="Foreground" Value="Red" /> </Style>

Inside a <Style> you can change any property on the target element, in our case the Foreground property that accepts a display brush.

Note that omitting the TargetType property limits you to only properties on FrameworkElement so you might want to define something more specific like TargetType="TextBlock" etc.

If you don’t specify a x:Key the style will be applied to all possible elements matching the TargetType.

Let’s look at CSS and XAML side-by-side:

span { color: Red; }

is roughly the same as:

<Style TargetType="TextBlock"> <Setter Property="Foreground" Value="Red" /> </Style>

Templates

Now we know how CSS (at least in a way) maps to XAML. Things are still pretty different and one of the things that you need to wrap your head around in XAML is templates.

Every control you drag to the surface is usually a collection of borders, shapes and other lower level framework stuff that makes up your control.

So if you want to modify the appearance of your control, you do that via the ControlTemplate. And this is where I am still not 100% sure what the common theme is, but I am getting better at it.

ControlTemplates can be applied either directly to the element, or via a Style inside a Setter.

<Style TargetType="TextBox"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="TextBox"> <!-- Your Template goes here --> </ControlTemplate> </Setter.Value> </Setter> </Style>

As you can see, all you do inside a <Setter> is pretty much the same as you would apply to the element itself in markup. If you have non-trivial values to set you can use the as you can do with almost all things in XAML.

This is actually an interesting concept that took some getting used to. In XAML you can specify each and any attribute of the element by using the <Element.AttributeName> syntax in case it’s not expressable by a simple literal value.

Now let’s assume I want to change the appearance of a TextBox to have a flat border. If you come from WinForms like me you’ll spend a fair amount of time hunting for a BorderStyle property that’s simply not existant in WPF.

The way to go here is: You guessed it, Control Templates.

The ControlTemplate allows you to replace the visual tree of your object and roll your own that suits your needs (makes it powerful, but rather hard to figure out). My naive approach to this was to simply define the border in WPF like this:

<ControlTemplate TargetType="{x:Type TextBoxBase}">
<Border Name="Border"
	BorderThickness="1"
	Padding="4,2"
	Height="Auto"
	BorderBrush="#FFCCCCCC">
</Border>
</ControlTemplate>

What happened was that I turned my TextBox into a border. No text entering, nothing. I changed the visual tree of the object to only contain a border, and that’s what I got.

It then took me a little while to figure out that you can’t simply change the tree without putting back in an element to write the text to. Apparently for textboxes you have to put in a ScrollViewer named PART_ContentHost.

So the correct way here is:

<ControlTemplate TargetType="{x:Type TextBoxBase}"> <Border Name="Border" BorderThickness="1" Padding="4,2" Height="Auto" BorderBrush="#FFCCCCCC"> <ScrollViewer x:Name="PART_ContentHost" /> </Border> </ControlTemplate>

This then gives us a nice flat border with 1 pixel thickness and a nice shade of gray instead of the gradient brush WPF uses by default.

Triggers

Another very important concept (at least to me) was triggers. Assuming we made our control look pretty, we may want to change it’s appearance once you mouseover it or focus it.

If you try like me using the VisualFocusStyle to do that you’ll soon notice that VisualFocusStyles are not applied when a user clicks the element, only when he navigates to it by keyboard. It was meant to provide UI hints for keyboard navigation, not to indicate focusing in any way.

The correct way to do stuff like OnFocus and OnMouseOver is by using Triggers. With triggers you can do something whenever a property matches a certain value. So in our case we can create a trigger that changes the border color whenever the IsFocused property contains the value True.

I am applying the trigger to my ControlTemplate we defined earlier:

<ControlTemplate.Triggers> <Trigger Property="IsFocused" Value="True"> <Setter TargetName="Border" Property="BorderBrush" Value="#FF00A9DA" /> </Trigger> </ControlTemplate.Triggers>

This trigger now only works with one Property/Value, IsFocused. But there is a way to verify that two conditions are met before the trigger fires using the MultiTrigger.

The concept is the same:

<MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsMouseOver" Value="True"></Condition> <Condition Property="IsFocused" Value="False" /> </MultiTrigger.Conditions> <Setter TargetName="Border" Property="BorderBrush" Value="Black" /> </MultiTrigger>

This MultiTrigger will only apply the black BorderBrush if IsFocused is false and IsMouseOver is true. Thus making sure the IsFocus style is not overridden and flickering whenever the user waves the mouse around.

DataTriggers

Triggers are only good for one thing: Firing if properties on the Visual Tree change. If you want to do something when something in your DataContext changes you need DataTriggers. These work by defining a Binding and a Value, but in essence work pretty much like normal Triggers, only that they work on anything you can bind to.

DataTriggers also come along in MultiDataTrigger and DataTrigger flavors.

DataTriggers are also the answer to most questions concerning MVVM asking “How can I show X from my ViewModel.”. The answer here is usually: "Define some boolean property (with INotifyPropertyChanged) and set up a DataTrigger to it. (This works for starting animations etc.. Everything.. This is crazy powerful!)

And that’s about all the stuff I spent most of my morning figuring out. I hope you get any useful information out of it. Because I quickly became frustrated with the content that’s out there.

Filed under net, programmierung, wpf

New website for dotless is up at www.dotlesscss.org

After some trouble with our previous hoster the old domain www.dotlesscss.com went offline.
Chris tried to resolve this issue, but things didn’t work out so the website was offline for almost 2 months now.

We where not completely offline since, I migrated the website to GitHub Pages some time ago and all documentation was moved over to the new GitHub Wiki. But we were still missing our shiny domain name we could point people to.

So I finally decided to give up on waiting for our old domain to come back and registered a new one:

http://www.dotlesscss.org

The old site is now available at the new name and we are trying to update all references to the new .org domain.
(And .org is more fitting for an OSS project anyway).

As for the project itself, I am planning a 1.2 release fairly shortly that should incorporate a ton of bug fixes and some improvements we made since version 1.1.

Please spread the word about this domain change. Thanks!

Ps: On a technical side, the new website is now powered by Jekyll on GitHub and the source is contained in the gh-pages branch on our GitHub repository.

Getting System.BadImageFormatException and no clue what&apos;s wrong?

What’s the default target platform on the .NET environment? Yep, it’s AnyCPU, meaning that a flag is set in your assembly file that specifies “this IL code can be either compiled into x64 or x86”, and the executing .NET framework will then decide what platform to choose based on the OS that’s running.

If you are running on a Win7 x64 machine you’ll execute a native x64 application, if you run on a 32 bit Windows you’ll run a 32 bit application.

When in doubt you’ll want to default to AnyCPU and only switch to x86 or x64 explicitly if you are doing some native P/Invoke or other weird stuff. So for 90% of developers AnyCPU is the perfect target platform and they don’t even know what goes on behind the scenes. They just compile once and run on any Windows with a .NET framework.

Now they screwed it up!

Whenever you create a new Project in VS2008 it will default to AnyCPU, everyone is happy.

Fast forward, VS2010 comes along and changes this default behavior:
In Visual Studio all class libraries default to AnyCPU, but all WPF Applications and Console Applications default to x86

Do you see the implications here? You start out with a clean AnyCPU solution like this one:

Once you add a Console Application you end up with:

As you can see, for no good reason (it’s only two blank projects after all) Visual Studio changes the platform to Mixed and sets the ConsoleApplication to x86!

Why is this so bad?

Well, if you are running on a x64 machine, and try to run unit tests inside your library project (as most of us do) you end up running a x64 process that is linked to a x86 assembly!

You don’t need to be a genius to figure out that this is not going to work. You’ll see a System.BadImageFormatException pop up with no good explanation. (Apparently the Platform dropdown in the Toolbar was also removed in VS2010!)

The “reason” for this crap

This is the explanation DJ Park (C# IDE, Program Manager) gives on Microsoft Connect about the change of the defaults:

To provide some context, the motivation for the change is to alleviate the pain that customers are feeling when developing on a 64-bit OS – some examples being Edit and Continue (EnC) and P/Invoke scenarios. To elaborate on the EnC example, EnC is supported on a 64-bit OS provided that you’re debugging a 32-bit process. However, by defaulting to AnyCPU, processes are automatically run as 64-bit, which means that EnC will not work unless you change the platform target to be x86

Have you ever used Edit and Continue? Hell I mostly run without a debugger attached and they are doing stupid things like that because they want to allow me to change code while I debug a program. Are you kidding me?

Not to mention the hilarious post quoted that tries to argue that AnyCPU is usually not worth it. Listing reasons 99% of programmers don’t care about at all.

Just to round this up: If you compile something to x86, you can still run it on a x64 Windows. Windows features a x86 “emulation layer” called Windows on Windows (it’s inside your C:\Windows\SysWOW64 folder) that allows you to run x86 applications on a 64 bit operating system. It works, but why would I want an abstraction layer if I could just as easily run a native 64 bit application on my 64 bit OS?
We are talking about a change of runtime characteristics for a tiny facilitation in development, and that’s not good in my opinion.

Filed under net, programmierung

The small things can cause the biggest troubles: List&lt;T&gt;.AddRange and GetHashCode

I just spent some hours performance optimizing an application I wrote a while back. The architecture was actually quite nice and I had implemented my own Lazy-Loading using DynamicProxy. Things worked great and performance was never an issue.

Fast forward 2 years: I left the company after the project was finished and development carried on. Additions to the code where made and after some time performance got a serious problem.

After hours of profiling I finally found the issue: Apparently List<T>.AddRange invokes GetHashCode on all items you add to the list.

Why is that a problem? Well: My Proxy objects where designed to return some key data that was eagerly fetched (stuff like Id, and some filter columns) and once the filter logic had narrowed down the list of thousands of items to the 2 or 3 that were going to be displayed, the Proxy transparently fetched the real data from the database and cached it. So every object in itself was doing a select once a method besides the prefetched data was requested.

I hadn’t thought of GetHashCode and any call to GetHashCode was not handled directly in the Proxy but caused a lazy load. And since .Add does not call GetHashCode but AddRange does, the bug never came up during development.

Imagine my face when I saw this profiler graph:

image

Needless to say that fetching 64 items from the database instead of 1 really brought the app down to a crawl.

Filed under net, programmierung

How to use different layout containers in WPF

WPF is different, that much I knew before I started learning it. But understanding really how different it is really takes a lot of time and effort. Especially when used to Windows Forms and HTML+CSS, WPF feels very alien in it’s way how to do layout. Here is what I learned:

StackPanel:

StackPanels are used to layout elements horizontally stacked onto each other.

image

By default the elements inside a StackPanel will take up their set height and you can make them fill the whole width by setting their VerticalAlignment to Stretch

They will however never fill the full height of the container when it is resized, no matter how your HorizontalAlign property is set. If the above container got resized in height the buttons would still stick to the top with their individual heights staying just the same.

WrapPanel:

They are the same as the StackPanel, just in vertical. They stack elements vertically and reorder them if there is no more space vertically. However they also don’t allow them to fill the vertical space available to the control.

image

The Dockpanel:

Where both WrapPanel and StackPanel don’t allow Elements to fill vertical space (even with HorizontalAlignment to Stretch) the DockPanel will do just that by default:

image

The trick here is that only the last child really fills the panel, so while resizing the height will resize all 3 buttons, a horizontal resize will only cause the third button to change size. This has to do with the LastChildFill property, where Button3 is considered the filling element.

Why am I telling you this? Well, turns out most UIs look something like this:

Some header, then one filling list that should resize and then some controls around the edges. Making the list resize with the parent container can’t be achieved by the other panels at all. You have to use a DockPanel and use the DockPanel.Dock attributes on your child controls:

<DockPanel Margin="0,0,0,0">
	<TextBlock DockPanel.Dock="Top" Text="Hello World" />
	<TextBlock DockPanel.Dock="Bottom" Text="Bottom" />
	<Button Content="Button3"></Button>
</DockPanel>

This will make the last element fill all available space left by the elements that where docked to the sides like this:

image

Once you understand these three layout concepts, you can build pretty much everything by nesting panels within each other. There is however also the GridPanel that lends itself very well to creating forms and other stuff that has to be aligned on a grid. But I won’t go into that in this post (and I think it’s markup is just awful. HTML4 tables were more intuitive to write)

Filed under net, programmierung, wpf

Good ideas worth spreading: SystemDateTime abstractions

I brought this example up a lot on this blog, but while looking at the code of Mark Nijhof yesterday I noticed a rather nice solution to my ongoing problem of abstracting away System.DateTime.Now calls for testing purposes.

As stated before: Don’t make your tests depend on external factors like the current time or Date, and I even had a solution until now that solved the problem rather nicely through a static factory that returns an instance to your DateProvider.
Why a global factory? Simple: having your IDateProvider be a mandatory dependency on all your objects and services will quite simply clutter up your design. IDateProvider is by no means a really important dependency, and modeling it the same way as say IImportantBusinessRule would not only require you to think about that DateTimeProvider in every test that you run against your object, but also reduce the readability of your constructors dramatically.

What I didn’t think about when writing my IDateProvider abstraction almost a year ago was that with C# 3.5 and lambdas, passing around a function is essentially the same as using a strategy class, but with a lot less ceremony. And obviously so thought Mark Nijhof when he wrote Fohjin (a very nice CQRS example you really should check out on GitHub).

public static class SystemDateTime
{
    public static Func<DateTime> Now = () => DateTime.Now;
    public static void Reset()
    {
        Now = () => DateTime.Now;
    }
}

So simple yet so elegant. In your tests you hardly have to think about this stuff, but if there is a test that depends on the date you can just go ahead and set it like this:

[Fact]
public void ctor_SetsDateAddedTo_CurrentDate()
{
    SystemDateTime.Now = () => DateTime.MaxValue;
    var orderLine = new OrderLine(TestData.Product, 1);

    Assert.Equal(DateTime.MaxValue, orderLine.DateAdded); }

It’s just a small touch, but it saves you 2 classes and still solves the problem nicely.

Beware of &lt;Button IsDefault=&rdquo;True&rdquo;&gt; in WPF/Silverlight

I’ve spent the better part of my weekend finding this bug and thought I’d share it in case someone else is having the problem. I’m building a WPF user interface with a NServiceBus backend and started noticing that sometimes changing data on the client didn’t generate UPDATE statements in my Database. I first assumed it had to do with my backend code, then I started digging through the various libraries I am using (NHibernate and NServiceBus) to find the problem.

After 2 days debugging through the backend code I finally found out that it’s the WPF application that sometimes sent wrong data. The scenario is quite simple:

image

This very simple dialog uses a StringFormat to display the Price field. This prevents me from using any other binding than a UpdateSourceTrigger=”OnLostFocus” because otherwise it would reformat the field on every key-press. Rendering it unusable due to a jumping focus caret. 

The issue was that upon hitting Save, sometimes the Save method was executed before the data was bound to the model, sometimes the other way around. I genuinely thought I had a race condition until I noticed one little thing: Since it’s a decimal field I usually fill those in by using the number pad. That also led to me hitting the Enter quite often without thinking about it, thus invoking the Save method while still having the focus on the Price Textbox.

If you set a Button to IsDefault=”True” and hit Enter the Command will be executed without triggering the OnLostFocus Databindings in your Textbox, making your code act on stale model data. The only way around this is to either use UpdateSourceTrigger=”OnPropertyChanged” (not always applicable) or remove the IsDefault attribute from your form.

I still believe this is a bug in WPF, but at least now I know about it and can avoid it.

Filed under net, programmierung, wpf

WPF FormatString and it&rsquo;s localization bugs

As some of you may know, I am from Austria. That means that I get to pay my bills in Euro and we format our decimals with a comma instead of a period (yes I know I’m weird).

So naturally my culture setting is de-AT and I really expect to see my decimals formatted this way: € 19,99
Turns out, WPF doesn’t give a damn and if you use FormatString in a binding it will just go ahead and return en-US formats!

<TextBox Text="{Binding Path=Model.Price, StringFormat=\{0:c\}}"/>

This is a bug in WPF and has been there for more than 2 years now from what I can gather. There is a fix to it as suggested by Nir Dobovizki, who coincidentally also has a pretty cool CheatSheet on WPF Databinding that I now have taped to the wall.

For the sake of completeness here is the code you have to put in your App startup code (I’ve thrown it in my App constructor):

FrameworkElement.LanguageProperty.OverrideMetadata(
    typeof(FrameworkElement), 
    new FrameworkPropertyMetadata(
        XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));

While at it I also found out another pretty cool thing that managed to save me a lot of markup in XAML: MultiBinding! You can apply StringFormat to single elements through the {Binding} blocks, but sometimes you want to show stuff like “Showing Page x of y” somewhere.
My naïve approach was to just create 4 elements and bind 2 of them to the appropriate values. As Brian points out in his post on WPF StringFormat you can just do stuff like this:

<TextBlock VerticalAlignment="Center" Margin="0, 0, 0, 10">
    <TextBlock.Text>
        <MultiBinding StringFormat="Showing Page {0} of {1}">
            <Binding Path="CurrentPage" />
            <Binding Path="NumberOfPages" />
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

The StringFormat attribute works exactly like the String.Format method whereas the <Binding> children are the parameters passed into it. Pretty cool to say the least.

Now if only someone explained to me why WPF Grids have this hideous way of cluttering up my markup with Grid.Row=”0” Grid.Column=”1” I may finally make my peace with WPF (aka the display technology I stayed away until now because learning it seemed like an impossible task)

Filed under net, programmierung, wpf

Untangling the dependency ball! Windsor + NServiceBus + Caliburn + Fluent Nhibernate in one package

confusing-road-sign-large-web-view

Unfortunately nu is still falling short on one thing: Making sure that all the stuff you install is actually compatible with the other stuff you have already installed. There is a ticket for this and I’m fairly confident this will get resolved (please vote the ticket up), but for now I was back to figuring out what version of what framework to use to make my app compile.

As always, the main problem was Castle.Core, being present in 3 different versions. (NSB used version 1.1, Caliburn 1.2 and the latest Windsor release targets 2.5)

I decided to back down and use 1.2 since there is a NHibernate gem for 1.2 and a Windsor gem for 1.2. I’m now using NHibernate 3.0 alpha so think about using this “stack”.

Anyway, this is a collection of:

  1. NServiceBus 2.0 .NET 4 (2.0.0.1219)
  2. NServiceBus.ObjectBuilder.CastleWindsor
  3. Castle.Windsor (2.1)
  4. Caliburn 2.0 (still unreleased from the trunk)
  5. NHibernate 3.0.0.1002
  6. FluentNhibernate 1.1 (Updated to NHibernate 3.0)
  7. AutoMapper

Disclaimer: The whole thing is built for .NET 4.0 and works on my machine. Don’t blame me if it’s broken for you.

Anyway. You can download the whole package of libraries here: castle-stack.rar

Weird errors with .NET Framework Client Profile referencing Full Profile Assemblies

I am currently working on a little demo project with NServiceBus and ran into this so I thought I’d share it:

If you create a new WPF project in VS2010 it will target by default the .NET FX Client Profile. That’s nice for a  number of reasons, but you will see very weird behavior once you reference an assembly that requires the full .NET profile.

In my case it was NServiceBus that I was referencing. Although the using directives where there, and I got full IntelliSense (and the reference showed up in VS) I got this compile error:

image

The code in question looks innocent:

image

Well: The reason for this weirdness is the .NET Client Profile. NSB requires stuff that’s not in the Client Profile thus the compiler will not resolve the reference. Visual Studio has no clue about that and isn’t displaying meaningful errors.

The solution is obviously simple: Go to the project preferences and select the appropriate Target framework:

image

Hope this helps!

Filed under net, programmierung

My Photography business

Projects

dynamic css for .NET

Archives

more