Tuesday, 20 June 2006

The sdk team has published all the WPF beta 2 samples as a zip. They are right here, http://www.wcsdkteam.members.winisp.net/wpfsamples.zip. Leave comments about problematic downloads at the sdk blog.

Tuesday, 20 June 2006 13:35:01 (Romance Standard Time, UTC+01:00)  #    Comments [1]  |  Trackback
 Tuesday, 13 June 2006

POCO power is announced by Roger Johansson, a lead developer of the NPersist OR-Mapper.
He writes: 'NPersist entities now supports 2 way databinding and edit cancels straight out of the box while still being fully POCO.
So as far as I know,
NPersist is the only .NET mapper capable of this while being POCO (at design time that is)'

The question I ask myself is, do you really want this? I admit I haven't used npersist for long, because I switched to nHibernate. But, having read Roger's blog for some time, I believe they are quite advanced in the proxy area, using IL.Emits all over the place for incredible speed (the only way to do it!). They certainly seem to have taken this path, giving as much luxury to the developer by doing all kinds of stuff dynamically. And yes, edit cancellation certainly seem like a nice feature to have out of the box. 2 way binding as well.

But then again, what if I want to switch to WPF? It supports the old way of propertynameChanged events, but I'd rather use the new Avalon flavor.
And I have built my own canceling, by using structs as the backing store of my properties. What if I want the 'loaded' state of my objects to also serialize, then I want my own solution where I can easily do that.

By doing too many things that are hard to follow for a developer, you will confuse them.
Most importantly, by doing too many things, you are locking developers into your technology.

I'm against that.

Then again, I'm also a bit jealous. I had to do all of that myself! I hope that their puzzle-framework uses a pluggable architecture, where you use a configuration file to 'plug in' capabilities to the proxy system, even allowing custom capabilities to be created. That would be awesome.

 

(If your into that kind of stuff, your best bet is the Castle framework. Check it out.)

Tuesday, 13 June 2006 12:19:48 (Romance Standard Time, UTC+01:00)  #    Comments [4]  |  Trackback
 Monday, 12 June 2006

When you are creating a layout in Xaml, you should be careful to take into account the width you have left. Yes, WPF will try to be smart and scale your controls, but what if the content of your control does not want to be scaled?

Paste this into Xaml-Pad and resize your Window:

<Grid Width="Auto" Height="40" xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
            xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
            xmlns:d='clr-namespace:System.Windows.Data;assembly=PresentationFramework' >
<Button HorizontalAlignment="Left">A lengthy button</Button>
<TextBlock HorizontalAlignment="Center">An longer TextBlock</TextBlock>
</Grid>

Nick Thuesen has a solution for this. He has created 3 rangeConverters that allow you to plug in a width and set a range where you would like your control to be visible. That is cool, I like it, I will use it.
In my specific case though, I wanted to collapse the content of a control based on the width of it's container. Basically, the container is a border, and it's content is a stack panel with some text boxes. The container is sized by an algorithm, so the container is more important then the content. The panel that does this scaling is surrounded by a slider, which zooms the controls accordingly. When enough space is available, the content should become visible.
Since I do not know the range in which the content should be shown, I can't use his controls.

It was dead simple to create my own though. Instead of using a single binding converter, I've used the MultiValueConverter to be able to bind to multiple properties.

public class ClippingToVisibilityHiddenConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
Debug.Assert(values.Length == 2);

double availableWidth = Double.PositiveInfinity;
Double.TryParse(values[0].ToString(), out availableWidth);

double desiredWidth = 0d;
Double.TryParse(values[1].ToString(), out desiredWidth); // possibly unset

double margin = 0d;
if (parameter != null)
Double.TryParse(parameter.ToString(), out margin);

Console.WriteLine("Desired: {0}, avail: {1}", values[1].ToString(), availableWidth.ToString());
return desiredWidth > (availableWidth-margin) ? Visibility.Collapsed : Visibility.Visible;
}

public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new Exception("not implemented");
}
}

Usage is equally simple:

<StackPanel.Visibility>
<
MultiBinding Converter="{StaticResource ClippingConverter}" ConverterParameter="15" >
<
Binding Path="ActualWidth" RelativeSource="{RelativeSource AncestorType={x:Type ContentPresenter}, AncestorLevel=1}" />
<
Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}" />
</
MultiBinding>
</
StackPanel.Visibility>

There you go, I hope you're happy with it! Confusion though about the ActualWidth property of elements....

My custom panel that does the layout, determines the desired size of the elements by doing a measurement of the element. Then at the arrange-pass, it calls an arrange on the element with a size possibly smaller then it desires. Somehow, when you read back the ActualWidth, DesiredSize, RenderSize or what else you can think of, you will never find that passed-in size.

Well, call me st00pid, but I would have expected the RenderSize to let me get to the .... rendered size..  ;-)
It does not.

Since I so desperately do want to find that 'clipped' size, I set the render size myself, after the arrange:

Size s = new Size(days * pixelsPerDay, uie.DesiredSize.Height);
uie.Arrange(new Rect(new Point(tsLinks.Days * pixelsPerDay, 0), s));
uie.RenderSize = s; // oh dear

It's definition in the SDK: Gets (or sets, but see Remarks) the final render size of this element.
So, the remarks then: Do not attempt to set this property, either in XAML or in code, if using the Windows Presentation Foundation (formerly code-named "Avalon") framework-implemented layout manager (nearly all common application scenarios will be using this framework layout manager). The layout manager will not respect sizes set via this property directly...

Yikes.

I like feeling naughty, but feeling this naughty can't be good.
I'll keep it in though, until I find a way to bind to the actual ActualWidth.

Monday, 12 June 2006 14:38:30 (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback

Everybody (and their grandmother) has blogged about the name change of winfx to .Net Framework 3.0. Their grievances are mostly focused on the weird dependencies that are created: framework 3.0 relies on framework 2.0 to be installed?! Also, winfx is perceived as a very cool name by the masses (me included!).

But when you think about it, this also allow you to tell your clients: 'you need the .Net Framework 3.0 installed to run this incredible piece of software'. They will also be much more inclined to install an update, versus an add-on.
So, it is very confusing, but in the end maybe for the best.

Brad Adams is answering questions.

Monday, 12 June 2006 13:41:14 (Romance Standard Time, UTC+01:00)  #    Comments [1]  |  Trackback
 Thursday, 08 June 2006

I always use Expression Interactive Designer when I want to see the full default style of a control, but here I have found a equally easy way: just dump it into XML.

Style style = FindResources(typeof(Button)) as Style; //Get button's default Style
if (style != null)
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.IndentChars = new string(' ', 4);
StringBuilder strbuild = new StringBuilder();
XmlWriter xmlwrite = XmlWriter.Create(strbuild, settings);
XamlWriter.Save(style, xmlwrite);//Use XamlWriter to dump the style
return strbuild.ToString();
}

It uses the findresources method to find a style and then just writes it out. Might come in handy!

Thursday, 08 June 2006 19:43:13 (Romance Standard Time, UTC+01:00)  #    Comments [4]  |  Trackback
 Wednesday, 07 June 2006

My previous post was about not being able to bind to a named element outside of your scope. With the help of some great people, we figured out a workaround: you can bind to an ancestor. So, this does work:

<StackPanel DataContext="{Binding ElementName=lb, Path=SelectedItem}">
<
ListBox Name="lb" ItemsSource="{Binding Source={StaticResource InventoryData}, XPath='Book'}" IsSynchronizedWithCurrentItem="True" />
<
local:CustomItemsControl ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type StackPanel}}, Path=DataContext}" />
</StackPanel>

This has a listbox that binds to a datasource (xml this time) and a stackpanel above it binds it's datacontext to the selecteditem of the listbox.
Obviously this has all kinds of nasty smells surrounding it.... Next please!

We might not be able to bind to a named element outside of scope, but if we can bind to an ancestor, chances are good that we can bind to a staticResource as well. So let's introduce a CollectionView around our XML datasource. In the Window.Resources:
<CollectionViewSource x:Key="InventoryView" Source="{Binding Source={StaticResource InventoryData}, XPath='Book'}" />

And then we can bind to the currentitem of this view, instead of the ugly datacontext of the parent stackpanel:

<StackPanel >
<
ListBox Name="lb" ItemsSource="{Binding Source={StaticResource InventoryView}}" IsSynchronizedWithCurrentItem="True" />
<
local:CustomItemsControl ItemsSource="{Binding Source={StaticResource InventoryView}, Path=CurrentItem}" />
</
StackPanel>

This is a good enough workaround for now. ;-)

Wednesday, 07 June 2006 19:40:44 (Romance Standard Time, UTC+01:00)  #    Comments [2]  |  Trackback

I've been working hard on seemingly simple functionality. I have a usercontrol (derived from ItemsControl) which has a panel (the itemshost) and a few other things like so:

<ItemsControl x:Class="VisualizerUsercontrol.myVisualizer"
              x:Name="parentControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <ItemsControl.Style>
    <Style TargetType="{x:Type ItemsControl}">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="{x:Type ItemsControl}">
            <StackPanel Orientation="Horizontal">
              <Button>press me</Button>
              <ScrollViewer VerticalScrollBarVisibility="Auto">
                <StackPanel Orientation="Horizontal"
                            IsItemsHost="True" />
              </ScrollViewer>
            </StackPanel>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>
  </ItemsControl.Style>
</ItemsControl>

When instantiating the control on a window, I bind it's ItemsSource to some other control, like a listbox's selectedItem. This of course, for a master-detail view. The bug is that this ItemsControl is unable to resolve it's ItemsSource, because the Element for which it is looking, is in another scope.

That actually is kind of unpleasant, and I hope to find a workaround for it. I appear not to be alone in this finding, and the consequences of it really limit the use of a usercontrol severely.

Wednesday, 07 June 2006 15:29:55 (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback

I've completely rewritten the RssBandit to Grazr converter, so that alphabetic order is used. That looks way nicer, doesn't it?

Program.cs (4.49 KB)

Wednesday, 07 June 2006 13:54:35 (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback

People that know me, know that I love Resharper. They now have a 2.0 version for Visual Studio 2005 and my bet is that I will love it as soon as I try it. But there was always one thing that I disliked about Resharper: the caching of the solution took ages on big projects.

Visual Studio 2005 gives us some refactoring tools and code snippets. Although they lack the power of Resharper, they will do for me. But what I can not live without is the fast code navigation that Resharper brought us. Their type navigator works instantly and that feels so incredibly smooth and silky, I just can't do without.
The last couple of months, I have used a new free tool that brings the instant navigation power without the caching costs. DPack has been pushed to the limits and performed incredibly.

Of course, I still miss a few Resharper features, such as 'find all references', which is light years ahead of the Visual Studio offering. But the speed of which my solutions now open does seem to make it up.

Try it, you might like it.

Wednesday, 07 June 2006 12:50:45 (Romance Standard Time, UTC+01:00)  #    Comments [1]  |  Trackback

Ouch, this really got to me. I upgraded to the May CTP, hacked my application to compile again and ran it.

The first screen of the application let's you choose a person to load. That went fine. But when loading more of this persons data on a following screen, Indigo completely freezes. That puzzled me quite a bit. Everything worked fine with the Feb. CTP, and I had not expected serialization problems. Wcf has a way of not throwing exceptions with serialization problems so I did not really have much to go on. I was retrieving a collection with about 14 objects in it. When I deleted a few objects everything went smooth again! So something new with maximum message size was going on?

The solution was not to up the maximum size (it was high enough), but to loosen the reader Quota's for my service.
A reader Quota is defined as: 'Gets or sets constraints on the complexity of SOAP messages that can be processed by endpoints configured with this binding'. The constraints include items such as a maximum element depth, a maximum length for string content within the message. The constraints protect against a class of denial of service (DOS) attacks that attempt to use message complexity to tie up endpoint processing resources.

There you have it. I guess they lowered the defaults.
<readerQuotas maxDepth="90000" maxStringContentLength="90000"
            maxArrayLength="90000" maxBytesPerRead="90000"
            maxNameTableCharCount="90000" />

That helped me for some time, but recently I've had to go higher again. Possibly the Wcf team could set the defaults to much higher values!

Wednesday, 07 June 2006 12:35:16 (Romance Standard Time, UTC+01:00)  #    Comments [0]  |  Trackback
 Monday, 05 June 2006

I've stumbled upon Grazr, which I really like (for now). It's a different way of viewing your blogroll in opml 1.1 format. It's snappy, cool and very web 2.0 like.

However, it's quite an ordeal to use something like opmlmanager or blogrolling to manager your opml file, while, let's face it.. you already have setup in your precious rss reader. I use the excellent RssBandit and I obviously just want to export my feeds (including categories) as opml and read it into Grazr. Well, it seems that the Grazr api is very strict about opml and only accepts version 1.1. RssBandit exports to a totally different schema (1.0) and conversion is needed. I found a converter by Matthew Hazlett for the native rssbandit format to opml 1.0. I adjusted it to use the opml 1.0 exports of rssbandit and spew out valid opml 1.1 files. The result can be seen on the right side of my site. I will categorize my feeds soon, for your viewing pleasure. I hope you like it.

There was one weird caveat though: when converted by xmlWriter with an encoding of utf-8, there would be a byte order mark that Grazr does not except. I've had to choose ascii encoding to get around this. If there are people that are going to use the converter and feel a strong need for utf, I will do an update and use the bytewriter to delete those pesky 3 bytes. My guess though that Grazr will lighten up and start accepting pretty soon. ;-)

Monday, 05 June 2006 21:52:31 (Romance Standard Time, UTC+01:00)  #    Comments [2]  |  Trackback
 Friday, 02 June 2006

My name is Ruurd Boeke and I am owner of the dutch company Sitechno. We do consultancy and hardcore development in .Net on enterprise applications, from client to server.

Categories I will post in are: winfx, or-mapping, mainstream .net and methodologies, with the occasional mad-man ranting in between.

I hope I'll be able to keep your attention.

With that, I declare this blog opened. ;-)

Friday, 02 June 2006 17:47:17 (Romance Standard Time, UTC+01:00)  #    Comments [2]  |  Trackback