Is Software Piracy Stealing?

This post is obviously not about WPF. I just read discussion on StackOverflow question: I’ve found my software as cracked download on The Internet, what to do?. Some of the answers and comments infuriated me so much I had to vent somewhere. Hence this post. Just to keep the tone of this blog, it will be in a form of tutorial – software piracy for dummies.

The question was posted by a software developer who found cracked version of his product. He asked what he could do to protect his product in which he invested six months of hard work.

I was surprised by the number of answers and comments that try to justify or minor software piracy in different ways. Even worse, StackOverflow is a place where almost all visitors are software professionals, the high number of them work that job for the money, and I didn’t expect there will be so much effort in explaining why software piracy is not so bad.

Just to be sure, I collected links that describe what is considered software piracy.

What is software piracy?

Numerous articles describe what software piracy is. Here are some top links from Google:

Read it, get your conclusion. As I read it, short interpretation is:

  • Vendors do not sell software like potatoes or cars, you do not buy the product, you buy the license to use the product.
    • Unless you are buying whole product, source code, and rights to do with it whatever you want. This kind of transactions are rare and are not subject of this post.
    • You can use software only under conditions product license allows
  • Copyright laws protect tThe software in the probably whole world. It is protected from unauthorized use and copying same as books and music.
  • Unauthorized use of software or use prohibited by the license is called copyright infringement of software. This phrase is how lawyers call it, for the rest of us it is software piracy
  • So, if you get and use software, but don’t have valid license, you are pirating software

How can software be pirated?

Here are some common ways of software pirating:

  • Copying software – most common. It’s making more installations than the license allows, usually one copy is bought and then it is given to family, friends or coworkers.
  • Downloading from internet P2P networks or file sharing sites (also very popular).
  • Buying counterfeit copies (look for internet ads that offer “huge discounts” and “OEM versions”). Call local wise guys, since it is usually big operation that involves production and distribution, so it needs an organization to run it.
  • Hard disk loading at computer shops

Ok, now that I’ve covered what software piracy is and how it is done, rant can begin.

About “Piracy is not stealing” idiocy

Let’s concentrate on software that has the price. You can argue it is not stealing, but pirating works something like this:

  • there is a commercial product that legally can be obtained only in exchange for money
  • pirate obtains said product without giving money in exchange for product

As we established before, this is called copyright infringement of software. Technically, it is theft, but it is illegal.

On the other hand, if you enter a shop and take some product without leaving money for it, it is called stealing.
If you take a cab ride and run without paying, it is called stealing.
If you stay in a hotel for a month and run without paying, it is called stealing.

So, if you get/take/obtain something that you should pay for, but without paying, it is stealing.

So, why we can’t call software piracy stealing? Pirates were expected to give money in exchange for the software license, but they didn’t. They got the product, but they didn’t pay for it. Ergo, stealing.

About “You should be happy somebody is pirating your software.”

That is one amusing sentence. The reasoning behind it is: “If there is no crack, your software is crap that nobody needs”. Maybe.
On the other hand, I don’t know how can anybody be happy when people steal from them. What kind of moron must I be to be happy in that situation?

Like I should put the following text on my web: “Hello world, I worked my ass of for last x months to make this software, that will make your life a little bit better, that will ease your job, that will make you some money, now come on and rip me off, make me and my family starve to death, so I know my software is worth something, and now I can die happy (and hungry)”.

A load of crap.
It is like this: “Hello world, I worked my ass off for last x months to make this software. Maybe it could make your life better, maybe it could ease your job, maybe it could make you some money. If you want to use it, I expect you to pay me. If you don’t have money, if you think it is not worth as much as I ask, or if you don’t want to pay me for any other reason, then you are free to continue your life and work the same way you did before, without my software. Thank you.”

I spent time creating software with the idea that it will be worth to people in one specific market. I don’t need pirates to justify my effort. Paying customers are more than enough justification. I would be very worried if there are no customers.

About “People who use pirated copies won’t buy anyway.”

This is the variation of the fallacy from the previous paragraph. The software is created with the idea of helping people do their job or have fun or whatever. Essence is making life better. Not all software achieves this, but that is another story.

My software (I hope) helps people do their job better, faster and easier. It makes them cash by helping them do more at the same time. I want some of that cash, and it is the amount they can save/earn in a couple of hours using my software. If they don’t pay me, I don’t want them to use it. Simple. My software, my rules and copyright law.

Somebody pulled Microsoft as an example. Allegedly, Microsoft was not very eager in fighting piracy in the developing countries as a method of penetrating the market. Moto was “they won’t buy anyway, so it’s better to let them use pirated windows than some other OS”. But there are very few companies that can do this. Small companies can’t wait 5-10 years like Microsoft can.

About “Price is too high, people cannot afford it.”

I found one very funny example in comments. It is about Adobe Photoshop pirating. The poster suggested that Photoshop piracy rate is very high because it is expensive. Well, it is quite pricey. And it should be. It is probably the best tool on the market (I don’t know for sure, not my area, please correct me if I’m wrong). Adobe has a large team working on a product. Those people earn their paychecks every month. Adobe must charge a premium if we want to have better versions of Photoshop.

Those who cannot pay are free to use any other tools they can afford. Photoshop is not the only tool in the world. There are other tools. Maybe not that capable, maybe they will take more time than Photoshop for the same tasks. Use what you can afford, and then save money and buy Photoshop if you need it.

You cannot buy big Mercedes for the price of small Chevrolet. Why is then considered normal to steal Photoshop if you cannot afford it?

About “You created software, it does not cost you anything to make copies.”

This is one where my head wants to explode. Even more so when I hear it from software developers who expects to get a regular paycheck. Basic naïve simplified software development economics:

  • n people created software for m months
  • for this m months, people working on software had to eat something, so they got some salary s
  • the total cost of development is about n * m * s plus some other expenses which in the end gives an awful lot of money (this is economics term)
  • now somebody estimates that we can sell a boat load of copies, and then it divides total development cost with a boat load, adds some margin and determines the unit price
  • now we wait to sell a boat load of copies just to break even
  • after we sell a boat load of copies, we start to earn and get filthy rich

So, yes, the act of copying software over internet costs almost nothing. The problem is that small software companies invest in development counting on future income. If pirates eat that income, it’s usually the end of company and product.

So, if you like some piece of software, buying it will help the company survive and upgrade product. Making free copies and pirating will likely kill it.

Software piracy is stealing

Third time’s the charm. This is the third title that says software piracy is stealing. This is for Google and other search engines. I want them to know what I think. I hope it’s clear.

What struck me on the StackOverflow site was that lots of the software developers condone piracy. There are some excuses used to justify pirating. The only conclusion is that developers are heavily pirating software.

Note:

  • I am not a lawyer. I don’t want to argue about copyright law interpretation. I wrote mine; you are free to do so in comments.

WPF Style Inheritance and Horizontal Alignment of WPF Controls in StackPanel

Summary

The post shows how WPF style inheritance can be used to simplify XAML. Code sample examines different ways to align horizontally several different WPF controls in StackPanel using:

  • no style
  • embedding style in controls
  • creating and applying the style to controls
  • using style inheritance

Problem: Aligning controls in StackPanel

Sample control contains a label, several radio buttons and one text box in one line. StackPanel seems like the perfect choice for this. Controls can be stacked vertically or horizontally, one next to the other. In my case, I want StackPanel to arrange the controls horizontally. Quick typing:



<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
<Label>Select delimiter:</Label>
<RadioButton GroupName="Delimiter" Content="Comma (,)" />
<RadioButton GroupName="Delimiter" Content="Semicolon (;)" />
<RadioButton GroupName="Delimiter" Content="Colon (:)" />
<RadioButton GroupName="Delimiter" Content="Other" />
<TextBox Width="20"/>
</StackPanel>


Run and the result was this mess:

WPF controls default vertical alignment.

Adding Vertical Alignment and Margins

By default, all controls are vertically aligned to the top and result is that all controls have a top at the same position. Since heights and baselines are different, aligning control bottoms would not work either. Aligning centers is the only option that can put control contents in line. Vertical alignment can be set directly to each control in XAML by adding:  VerticalAlignment="Center"

Controls are crammed one to the another because default margin is zero. To create space between the controls, the Margin property must be greater than zero.

For more information see this MSDN article: Alignment, Margins, and Padding Overview.

Creating a Style

Vertical aligning to center will be default alignment for the controls in my application, so I would like to have one style definition that will be available to the all controls. First step is creating a style. It can be done in several ways:

Create default style for each type of the controls:


<Window.Resources>
<Style TargetType="RadioButton">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="5,0,0,0" />
</Style>
<Style TargetType="Label">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="5,0,0,0" />
</Style>
<Style TargetType="TextBox">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="5,0,0,0" />
</Style>
</Window.Resources>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
<Label>Select delimiter:</Label>
<RadioButton GroupName="Delimiter" Content="Comma (,)" />
<RadioButton GroupName="Delimiter" Content="Semicolon (;)" />
<RadioButton GroupName="Delimiter" Content="Colon (:)" />
<RadioButton GroupName="Delimiter" Content="Other" />
<TextBox Width="20"/>
</StackPanel>

Result:
All WPF controls vertically aligned by center.
This works – controls are now aligned, but it is to much code – same properties are set for each type of controls.

Create named style and assign it to controls

Next step is to create style, give him a name and then assign it to the controls:


<Window.Resources>
<Style x:Key="BaseStyle" TargetType="FrameworkElement">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="5,0,0,0" />
</Style>
</Window.Resources>

<Grid>
<StackPanel Margin="10" Orientation="Horizontal" VerticalAlignment="Top">
<Label Style="{StaticResource BaseStyle}">Select delimiter:</Label>
<RadioButton Style="{StaticResource BaseStyle}" GroupName="Delimiter"
Content="Comma (,)" />
<RadioButton Style="{StaticResource BaseStyle}" GroupName="Delimiter"
Content="Semicolon (;)" />
<RadioButton Style="{StaticResource BaseStyle}" GroupName="Delimiter"
Content="Colon (:)" />
<RadioButton Style="{StaticResource BaseStyle}" GroupName="Delimiter"
Content="Other" />
<TextBox Style="{StaticResource BaseStyle}" Width="20"/>
</StackPanel>
</Grid>

This one is worse than the first solution. It has less lines, but assigning style to every control is making code hard to read and adding style to each and every control is pain in the lower back.

Note the target type property: TargetType="FrameworkElement" It is set to FrameworkElement which is the ancestor of all the controls I have on this form. But, be careful because there are WPF controls that are not derived from the FrameworkElement and this code will not work for them.

WPF Style inheritance

Fortunately, WPF styles can be derived from other existing styles. Procedure goes like this:

  • create base style and give it a name
  • create new style and add property: BasedOn="{StaticResource SomeBaseStyle}"

Now, I’m going to create base style for FrameworkElement and then I’ll derive styles for each type of control I have on my form:


<Window.Resources>
<Style x:Key="BaseStyle" TargetType="FrameworkElement">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="5,0,0,0" />
</Style>
<Style TargetType="Label" BasedOn="{StaticResource BaseStyle}" />
<Style TargetType="RadioButton" BasedOn="{StaticResource BaseStyle}">
<Setter Property="GroupName" Value="Delimiter" />
</Style>
<Style TargetType="TextBox" BasedOn="{StaticResource BaseStyle}" />
</Window.Resources>

<Grid>
<StackPanel Margin="10" Orientation="Horizontal" VerticalAlignment="Top">
<Label>Select delimiter:</Label>
<RadioButton Content="Comma (,)" />
<RadioButton Content="Semicolon (;)" />
<RadioButton Content="Colon (:)" />
<RadioButton Content="Other" />
<TextBox Width="20"/>
</StackPanel>
</Grid>
</Window>


It works like this:

  • base style defines VerticalAlignment and Margin properties for FrameworkElement (which is ancestor control for other controls in this example)
  • Label and textbox styles inherit from the base style and leave it as is. They are defined here so that we have default styles for the labels and textboxes, so there is no need for assigning style in the controls. This can be done because label and textbox are derived from FrameworkElement
  • Radio button style inherits from the base style, but also sets GroupName property, since it is the same for all RadioButtons on my form

Although this is bit more code compared to solution with one named style, I like it more because XAML looks less clutered to me. Even better, base styles can be put into Application.Resources and reused throughout whole application. More details on using Application.Resources can be found in this MSDN article: How to: Use Application Resources

How to Bind to ListBox.ItemsSource inside UserControl

Summary

The post describes two ways of WPF data binding to elements inside WPF user control. Example shows how to establish WPF user control data binding by:

Complete source code is available for download here.

Problem

While working on my project, I needed identical controls and functionality on several windows. The solution was to create WPF user control and use it in all windows.

Control I created contains ListBox , button, textbox and few other controls (panel, border). Creating this user control was easy – define the layout and add standard WPF controls. Step two is using this custom control in windows and other user controls.

Adding user control to other window or user controls is simple:

  • add a reference to a namespace (and assembly if the user control is not in the same assembly as Window where it will be used)
  • add a control to XAML

So, I added my new user control to the window, and next step is to define binding. Type ItemsSource=”{Binding myList}” and the red squiggly line immediately appeared, notifying me that there is no  ItemsSource in my user control.

Binding to Dependency Property in User Control

My user control is derived from UserControl , which does not have ItemsSource property. The first idea is to create a property on user control that exposes ItemsSource property.  The user control will have dependency property of type IEnumerable for ItemsSource, and listbox will have data binding that binds to this property. Consumers of this user control will then be able to bind to this property in XAML, just like standard listbox.

Binding to DataContext of User Control

While reading through UserControl properties, I noticed that I forgot about DataContext property. Second way can be to assign DataContext to my control and then bind ListBox inside my user control. Consumer will bind list to user control DataContext and inside user control, listbox will bind to that DataContext

User Control Example

I decided to test both of solutions to see which one feels better. For test, I created simple user control that contains two listboxes, one will be bound to DataContext, other to dependency property. Here is the code:


<UserControl x:Class="ListboxInUserControlDemo.ListboxInUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="myUserControl"
Height="300" Width="500">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="10"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ListBox ItemsSource="{Binding Path=.}" Grid.Column="0"/>
<ListBox x:Name="listBox2"
ItemsSource="{Binding ElementName=myUserControl, Path=MyItemsSource}"
Grid.Column="2"/>
</Grid>
</UserControl>

In above code, first listbox have ItemsSource bound to current DataContext. Specification Path=. is used to bind to current source (see Binding.Path Property for details). Specifying Path=. is not mandatory, it could be written like this: ItemsSource="{Binding}". I put it here just to remind myself what Path=. actually means.
The second listbox gets ItemsSource from dependency property MyItemsSource. Since ItemsSource is bound to property of this user control, there must be specified element whose property is bound to listbox, so there is: ElementName=myUserControl.

Most of the code behind is code needed to define dependency property:


using System.Collections;
using System.Windows;
using System.Windows.Controls;

namespace ListboxInUserControlDemo
{
/// <summary>
/// Interaction logic for ListboxInUserControl.xaml
/// </summary>
public partial class ListboxInUserControl : UserControl
{
public static readonly DependencyProperty MyItemsSourceProperty;

static ListboxInUserControl()
{
ListboxInUserControl.MyItemsSourceProperty =
DependencyProperty.Register("MyItemsSource",
typeof(IEnumerable), typeof(ListboxInUserControl));
}

public IEnumerable MyItemsSource
{
get
{
return (IEnumerable)GetValue(ListboxInUserControl.MyItemsSourceProperty);
}
set
{
SetValue(ListboxInUserControl.MyItemsSourceProperty, value);
}
}

public ListboxInUserControl()
{
InitializeComponent();
}
}
}

Consuming User Control in Window

Now we have user control defined. Next step is to put it into window and test behavior. To see difference between binding methods, example will contain two copies of the user control. One will bind to DataContext, while second will bind to dependency property. On each copy of user control, one listbox will show data, while other will be empty.


<Window x:Class="ListboxInUserControlDemo.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:lbUserControl="clr-namespace:ListboxInUserControlDemo"
Title="Window1" Height="400" Width="550"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<TabControl>
<TabItem Header="DataContext binding" >
<lbUserControl:ListboxInUserControl DataContext="{Binding TestList}"/>
</TabItem>
<TabItem Header="Dependency Property Binding">
<lbUserControl:ListboxInUserControl MyItemsSource="{Binding TestList}"/>
</TabItem>
</TabControl>
</Grid>
</Window>

Window contains TabControl with two TabItems. Each TabItem have one ListboxInUserControl.

There is nothing special in code behind of this window, standard constructor and initialization for TestList property:


using System.Collections.Generic;
using System.Windows;

namespace ListboxInUserControlDemo
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}

List<string> _testList;
public List<string> TestList
{
get
{
if (_testList == null)
InitList();
return _testList;
}
}

private void InitList()
{
_testList = new List<string>();
_testList.Add("Lorem ipsum dolor sit amet,");
_testList.Add("consectetur adipiscing elit. ");
_testList.Add("Duis mollis egestas ornare. ");
_testList.Add("Cras diam est, sollicitudin ");
_testList.Add("quis vulputate sed, lacinia.");
_testList.Add("Phasellus lorem nunc, fringilla eget posuere");
_testList.Add("sed, tincidunt nec felis. Ut non dui ut");
_testList.Add("metus auctor scelerisque quis ornare leo.");
_testList.Add("Integer eget purus tellus. Nullam ut urna dui.");
_testList.Add("Quisque sed enim magna, sed.");
}
}
}


So, let’s see what happens when I run this code.
The first user control on first TabItem binds to DataContext to TestList the property of a window. Left listbox in user control binds to that DataContext and it will show contents of TestList. Right listbox will be empty since there is no binding to the dependency property MyItemsSource.
Second user control binds dependency property MyItemsSource to TestList property of the window but does not bind DataContext. On this tab left listbox will be empty, and right listbox will show contents of TestList.

There it is. Two ways to databind to ListBox inside the user control. This, of course, works for all types of controls.
I prefer databinding with DataContext. Defining DependencyProperty adds lots of code in codebehind but does not save anything when you consume UserControl.

The complete code is available for download here.

How to Attach to MouseDown Event on ListBox

I wanted to create drag and drop functionality between two list boxes – user should be able to drag items from one ListBox to another.
For test, I created MouseDown event handler for list boxes. Here is XAML for window with two list boxes side by side:


<Window x:Class="ListBoxMouseEvents.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="316" Width="655">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition Width="20"/>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <ListBox x:Name="listBox1" Mouse.MouseDown="ListBox_MouseDown">
            <ListBoxItem>Lorem ipsum dolor sit amet,</ListBoxItem> 
        </ListBox>
        <ListBox Grid.Column="2" x:Name="listBox2" Mouse.MouseDown="ListBox_MouseDown">
            <ListBoxItem>Lorem ipsum dolor sit amet,</ListBoxItem>
        </ListBox> 
    </Grid>
</Window>

In codebehind, I added simple handler for the MouseDown events on both listboxes. Handler should popup messagebox with name of the listbox that triggered the event.


    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void ListBox_MouseDown(Object sender, MouseButtonEventArgs e)
        {
            ListBox listBox = (ListBox)sender;
            MessageBox.Show("MouseDown event on " + listBox.Name);
        }
    }

Press F5 and test. Clicked in the middle of the left listbox – MesasgeBox pops up with correct name. Same for right listbox. Then I accidentally clicked on that one item in the listbox and nothing happened. Item was selected, but no MessageBox. Obviously, ListBoxItem class handled event and it stopped propagating.

How routed events work in WPF

MouseDown is, like all mouse events in WPF, implemented as RoutedEvent. Mechanics of routed events is described in MSDN article: Routed Events OverView.
In WPF, events can be routed in three ways: bubbling, tunneling and direct routing. Direct routing is not interesting because event fires only in control where it originated. Bubbling and tunneling routing propagate event through the visual tree.

  • Bubbling routes event from control where event was invoked to successive parent elements until it reaches the root.
  • Tunneling routes event in opposite direction, starting with element tree root and propagates until it reaches control where it was invoked. These are called “Preview” events.

Bubbling and tunneling events are often implemented in pairs. Tunneling events are always invoked first, before corresponding bubbling event.
MouseDown is routed event that is routed by bubbling and his corresponding tunneling or preview event is PreviewMouseDown.

Routing MouseDown event in ListBox

ListBox control contains ItemsPresenter which contains ListBoxItems (there are other controls in between like border and scrollviewer, but they could be abstracted here because they by default handle MouseDown event same way as ItemsPresenter ). When I click inside ListBox, but not on ListBoxItem, MouseDown event is routed like this:

  • Event originates in ItemsPresenter which is first control to receive event. Default handler does not set Handled property to true and event is propagated to its parents, who also do not change Handled property, until it reaches the ListBox.
  • ListBox finds ListBox_MouseDown handler and it invokes it. Code shows MessageBox and does not change Handled property so event can be propagated further. If Window had MouseDown event handler, it would be invoked.

When I click on ListBoxItem inside ListBox following happens:

  • ListBoxItem is first control that receives event. It’s MouseDown handler have code that deals with the selected item inside ListBox (sets properties related to selection and changes visual appearance). Finally it sets Handled property to true. This suggests that event does not need further handling.

Work around: how to handle ‘handled’ routed events

Fortunately, there are two ways to work around this situation:

  • Use the “Preview” event which happens before the bubbling event. This event can be added in XAML. When using this approach, you should be careful not to set Handled property to true, because it will prevent bubbling events to be invoked.
  • Add handler by using the handledEventsToo signature of AddHandler(RoutedEvent, Delegate, Boolean). Limitation of this workaround is that it can be set only in code, not in XAML.

More details on this can be found in last section of MSDN article Marking Routed Events as Handled, and Class Handling.
Finally, here is the code that uses both approaches – one ListBox have preview event attached, while the other has handler added in code.
XAML:


<Window x:Class="ListBoxMouseEvents.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="316" Width="655">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition Width="20"/>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <ListBox x:Name="listBox1" Mouse.PreviewMouseDown="ListBox_MouseDown">
            <ListBoxItem>Lorem ipsum dolor sit amet,</ListBoxItem> 
            <ListBoxItem>consectetur adipiscing elit. </ListBoxItem>
            <ListBoxItem>Duis mollis egestas ornare. </ListBoxItem>
        </ListBox>
        <ListBox Grid.Column="2" x:Name="listBox2" >
            <ListBoxItem>Lorem ipsum dolor sit amet,</ListBoxItem>
            <ListBoxItem>consectetur adipiscing elit.</ListBoxItem>
            <ListBoxItem>Duis mollis egestas ornare.</ListBoxItem>
        </ListBox> 
    </Grid>
</Window>

CodeBehind:


    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            // Add handler. Note third parameter: handledEventsToo = true
            listBox2.AddHandler(UIElement.MouseDownEvent, 
                new MouseButtonEventHandler(ListBox_MouseDown), true);
        }

        private void ListBox_MouseDown(Object sender, MouseButtonEventArgs e)
        {
            ListBox listBox = (ListBox)sender;
            this.Title = "MouseDown event on " + listBox.Name;
        }
    }

Note that in this version text is displayed in the title of the window instead of MessageBox. I changed it because showing message box in PreviewMouseDown event was interfering with event propagation and item in left list box was not selected after click – looked like click never happened. It probably has something to do with the fact that there were other mouse events happening when I was closing message box. So, be careful with actions in preview event.

For drag/drop handling I will use second approach – adding handler that receives handled events. Drag and drop functionality needs information about selected item. I could get that myself in preview event, but why, when there is code in event handler of ListBoxItem.

AncestorType must be specified for RelativeSource in FindAncestor mode

Everything started when I tried to draw horizontal line inside a border element and I wanted line length to be same as the border width. Binding coordinates by using RelativeSource was the first thing I wanted to try (it was way before I found out that Stretch property is the simplest way to go).  After checking MSDN on RelativeSource, first version looked like this:


<Border Height="30" BorderBrush="Black" BorderThickness="1">
    <Line X1="0" Y1="5"
          X2="{Binding RelativeSource={RelativeSource 
                                       Mode=FindAncestor, 
                                       AncestorType={x:Type Border}, 
                                       AncestorLevel=1},
                       Path=Width}"
          Y2="5"
          Stroke="#000fff" StrokeThickness="1" />
</Border>

Mysterious error

When I finished typing, VS2008 XAML editor did not like it. Binding expression had red squiggly underline and when I put mouse over it displayed hint: “Mode must be specified for RelativeSource”.
OK, I checked syntax, looked fine.  I found example in the help file where “Mode”  keyword was omitted, so I tried that:


X2="{Binding 
     RelativeSource={RelativeSource FindAncestor, 
                     AncestorType={x:Type Border}, 
                     AncestorLevel=1},Path=Width}"

Something changed. Error message now says: “AncestorType must be specified for RelativeSource in FindAncestor mode”.
Aha moment: there must be something wrong with the syntax, maybe I missed comma or braces, maybe order of arguments. But everything looked fine. I tried following:

  • moved Path before RelativeSource
  • removed comma between Path and RelativeSource
  • removed Path keyword

Nothing worked. Time for Google. Search returned number of pages and I started reading. Some claimed that binding mode must be specified(OneWay, TwoWay, …). Most of them have link to WPF wiki page: Q5.3 – Source vs. RelativeSource vs. ElementName

I copied examples from that article, but got the same error. That was fishy. I copied code from two places and they didn’t work.

Simple fix for error that is not an error, but bug

Then I found comment on StackOverflow question Setting WPF nested control properties from the parent control where somebody wrote that this is VS 2008 bug and that simple rebuild solution will clear falsely reported error.
Clicked on “Rebuild Solution”, everything went fine and squiggly underline disappeared. Arrrgh. Half an hour lost just because I didn’t try to build project. And I usually do that very often.

Solution for wrong problem

After all this fun, it turned out that the above code was correct. Unfortunately, it did not work as expected. Border element that contains line does not have width specified, so X2 is equal to null. If I specify width on Border element, then Border does not expand to parent area. I tried with Width=”Auto”, both on Border and Line, but that did not work either – line was zero length. Last thing I tried was to bind X2 to ActualWidth of Border element. That was fun. XAML designer was confused – it drew border, then line inside. But border must contain line inside, so it redraw border two pixels wider. That changed ActualWidth property, so it forced line to redraw. This went on for few seconds and then it stopped. There was horizontal scroll bar, but it had no scroller, so I could not see how wide border and line are.

Finally, after few fun hours, I stumbled on Stretch property that all shapes have. It defines how  shape will fill its container. With this property, you can force shape to expand and fill container in all directions. Here is final XAML code for border that contains horizontal line that is stretched across border:


<Border Grid.Row="0"  Height="30"  BorderBrush="Black" BorderThickness="1">
    <Line X1="0" Y1="5" 
          X2="5" Y2="5"  
          Stretch="Fill" 
          Stroke="#000fff" StrokeThickness="1" />
</Border>

I tried to remove X2, but then it does not stretch. Also, X1 and X2 must different, does not matter which one is greater. If they are equal, line is not drawn.