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.