Неділя, 26 вересня 2010 р.

Border with exact 1 pixel width or height regardless of the screen DPI

Sometimes it is required to make border size exact of 1 screen pixel width or height in WPF.

In usual 96 DPI environment is is pretty simple, just specify "SpansToDevicePixels" property to "True":
<Border Height="1" SnapsToDevicePixels="True" Background="Gray" />

However, if the DPI is different, you may receive unexpected results.
If the DPI < 96, the line may not be visible at all, and if DPI > 96, two lines may appear sometimes instead of one.

To fix this, you need to specify height of the border in device independent pixel to exact match screen pixel. E.g for the DPI = 125, the Height should be 0.8.

To achieve this I create a special class PixelBorder and override MeasureOverride method:
public class PixelBorder: Border
{
    protected override Size MeasureOverride(Size constraint)
    {
        PresentationSource presentationSource = PresentationSource.FromVisual(this);
        return new Size(
               presentationSource.CompositionTarget.TransformFromDevice.M11, 
               presentationSource.CompositionTarget.TransformFromDevice.M22);
    }
}

And use it where needed:
<local:PixelSeparator SnapsToDevicePixels="True" Background="#AAAAAA" Margin="4"/>

This border will be stretched horizontally or vertically depending on parent panel.

Четвер, 8 квітня 2010 р.

Blurry Images in WPF and how to make them sharp

If you tried to insert image in the WPF, you may be disappointed to see that the sharpness of image is not constant.

For example, let's create a simple window and put an image on it.

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="301" Height="251">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Image Stretch="None" Source="ActivityMonitor.png" />
</StackPanel>
</Window>


You may be surprised to see that an image you just inserted is displayed not as you expected, instead it is blurry:

This happens because the image is displayed in the center of a window. If you resize the window - the image may become sharp and then blur again.

WPF uses device independent pixel coordinates in double format. And it is not a problem in WPF to draw the image in the non-integer coordinates, say, X: 22,5 and Y: 45,5.

To correct this, you need to add the following to the Image tag:
BitmapScalingMode="NearestNeighbor"

Full code will look like this:

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Title="Shapr Image"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="301" Height="251">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Image Stretch="None" Source="ActivityMonitor.png" RenderOptions.BitmapScalingMode="NearestNeighbor" />
</StackPanel>
</Window>
Now the image looks much better:

Середа, 23 грудня 2009 р.

Great article on AppDomain:
http://blog.lab49.com/archives/2355

Четвер, 15 жовтня 2009 р.

UV Outliner 1.3 is out

Finally, my tiny WPF project is released. It is UV Outliner.

I am a big fan of outliners.

It is astonishing what amount of information in our everyday life has a hierarchical nature.
I always wanted to be able to play with such information. Plans for life or for the day, travel information, meeting schedules, business plans, novels, or even blog posts are all examples of hierarchical information.

So I decided to share the results of my work with other people like me.

I hope UV Outliner will become a part of your life and will help you to be more productive.

http://uvoutliner.com

Субота, 13 червня 2009 р.

Correct way to keep selection in TextBox and RichTextBox visible after focus lost in WPF

WPF controls: TextBox and RichTextBox have no HideSelection property. Due to this, it is a bit tricky to make them to show selection after focus lost.

There are two possible solutions.

1. Defining separate focus scope in XAML
2. Adding and event handler (LostFocus) and set Handled property of RoutedEventArgs to true in code.

As the second one seems to be tricky, I will show how to implement this behavior with the first concept:

<Window
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<StackPanel>
<TextBox Margin="5">Some text here</TextBox>

<StackPanel Grid.Row="1" FocusManager.IsFocusScope="True">
  <ComboBox Margin="5">
  <ComboBoxItem IsSelected="True">123</ComboBoxItem>
  <ComboBoxItem>123</ComboBoxItem>
  </ComboBox>
</StackPanel>
</StackPanel>

</Window>

This code will create window with two controls (TextBox and ComboBox):

As you can see, both controls can have focus simultaneously. This happens because of the FocusManager.IsFocusScope property set to true which makes second control to be in a separate focus scope.

However, if new window is opened, focus on both controls will be lost.

You can read more about focus management in WPF here:
http://msdn.microsoft.com/en-us/library/aa969768.aspx

Середа, 11 лютого 2009 р.

How to insert image into FlowDocument at runtime

To insert image into FlowDocument at runtime you can use the following code:

FlowDocument document = new FlowDocument();
Image image = new Image();
BitmapImage bimg = new BitmapImage();
bimg.BeginInit();
bimg.UriSource = new Uri("c:\temp\image.png", UriKind.Absolute);
bimg.EndInit();
image.Source = bimg;
document.Blocks.Add(new BlockUIContainer(image));

Пʼятниця, 7 листопада 2008 р.

How to set initial focus to specific WPF control in XAML

Setting initial focused control in WPF is easy. Just use the FocusManager.FocusedElement attached property:

<Window FocusManager.FocusedElement="{Binding ElementName=MyEdit}" >
<TextBox Name="MyEdit" />
</Window>