WPF: DataTemplates and Design-Time data

It seems to be useful to have a possibility to edit DataTemplate rendered with Design-Time data.

First, let’s consider the following ViewModel interface:

internal interface IBookViewModel
{
    string Author { get; set; }

    string Title { get; set; }
}

Let’s also create a separate XAML-file for ResourceDictionary where the DataTemplate will be located:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:viewModel="clr-namespace:App.ViewModel"
                    mc:Ignorable="d">
    <DataTemplate DataType="{x:Type viewModel:IBookViewModel}">
        <StackPanel Orientation="Vertical">
            <TextBlock Text="{Binding Author}" />
            <TextBlock Text="{Binding Title}" />
        </StackPanel>
    </DataTemplate>
</ResourceDictionary>

Second, let’s edit the DataTemplate using Blend for Visual Studio 2012 (see Expression Studio 4.0: Create or modify a template):

  1. Open the solution in Blend.
  2. Locate the XAML-file containing the ResourceDictionary using the “Resources” panel.
  3. Locate the DataTemplate in the list of resources by its Key.
  4. Click “Edit Resource” button.

Blend will show the message “BookViewModelTemplate.xaml cannot be edited in the Design view.”

Third, to display Design-Time data attribute d:DataContext must be used to provide the Design-Time data for the designer.
Also, there is d:DesignInstance markup extension to simplify the Design-Time instance creation.
Blend uses the following Design-Time-related XAML-namespaces (see DesignData MVVM support in Blend, VS2010 and WPF/Silverlight):

xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"

To provide the Design-Time Data instance, let’s create a class that will implement the ViewModel interface and contain the appropriate data:

internal sealed class DesignBookViewModel : IBookViewModel
{
    public DesignBookViewModel()
    {
        Title = "Test title";
        Author = "Test author";
    }

    public string Author { get; set; }

    public string Title { get; set; }
}

Finally, after experiments it seems the d:DataContext attributes does not work for DataTemplate element directly, but the immediate child element of the DataTemplate.

The following result examples are identical. Both work just fine!

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:viewModel="clr-namespace:App.ViewModel"
                    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                    mc:Ignorable="d">
    <DataTemplate DataType="{x:Type viewModel:IBookViewModel}">
        <StackPanel Orientation="Vertical"
                    d:DataContext="{d:DesignInstance Type=viewModel:DesignBookViewModel, IsDesignTimeCreatable=True}">
            <TextBlock Text="{Binding Author}" />
            <TextBlock Text="{Binding Title}" />
        </StackPanel>
    </DataTemplate>
</ResourceDictionary>
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:viewModel="clr-namespace:BlendabilityDataTemplate.ViewModel"
                    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                    mc:Ignorable="d">
    <viewModel:DesignBookViewModel x:Key="DesignBookViewModel" />
    <DataTemplate DataType="{x:Type viewModel:IBookViewModel}">
        <StackPanel Orientation="Vertical"
                    d:DataContext="{Binding Source={StaticResource DesignBookViewModel}}">
            <TextBlock Text="{Binding Author}" />
            <TextBlock Text="{Binding Title}" />
        </StackPanel>
    </DataTemplate>
</ResourceDictionary>

Enjoy!

P.S. There is also another approach (out of the scope of this post) – create a DataSource using Blend. It implies adding additional XAML-file that defines ViewModel instance (i.e. initialization).
The disadvantage of this approach: the ViewModel can be just an interface or concrete class, but without public setters – no way to set property values using XAML.
More details here:

  1. DesignData MVVM support in Blend, VS2010 and WPF/Silverlight.
  2. Blendability Part I – Design time ViewModel.

References:

  1. Mastering XAML (Design-Time attributes) by Adam Nathan.
  2. WPF 4.5 Unleashed, Adam Nathan.

StackOverflow references:

  1. What approaches are available to dummy design-time data in WPF?.
  2. Setting design time DataContext on a Window is giving a compiler error?.
  3. Making a DataTemplate blendable.
  4. Design time data for datatemplate in xaml.

FreeBSD: graphics/dri build failed

Have just installed FreeBSD 10.0-RELEASE. Build of graphics/dri port failed with the compilation error. The same problem and solution described here:

In file included from i830_context.c:28:
In file included from ./i830_context.h:31:
../../../../../src/mesa/drivers/dri/intel/intel_context.h:249:4: error: unknown type name 'drm_intel_context'
   drm_intel_context *hw_ctx;
   ^
1 error generated.

Post by gustopn » 14 Nov 2013, 11:45

And for those of you, who do not want to have a X without Intel KMS support, you need to remove /usr/local/include/intel_bufmgr.h in order for DRI to compile. The problem is that it looks for intel_bufmgr.h but in the wrong version; /usr/local/include/libdrm/intel_bufmgr.h is the right/new one.

As a final solution consider renaming the /usr/local/include/intel_bufmgr.h file.

Enjoy!

Extract tar.gz-archives with tar-cs library

Let’s implement the code to demonstrate how to extract files and directories from tar.gz-archives.

The code:

using System;
using System.IO;
using System.IO.Compression;
using tar_cs;

/// <summary>
/// Example of tar-cs library usage to extract tar.gz-archives.
/// Please use the latest version (from trunk) of the library.
/// </summary>
public static class TarGZip
{
    public static void Extract(string inputFile, string outputDirectory)
    {
        using (FileStream inputStream = File.OpenRead(inputFile))
        using (Stream tarStream = UnGZipSteam(inputStream))
        {
            var tarReader = new TarReader(tarStream);
            while (tarReader.MoveNext(false)) // Moves pointer to the next file in the tar archive.
            {
                ExtractTarEntry(tarReader, outputDirectory);
            }
        }
    }

    /// <summary>
    /// Since GZipStream.Position Property is not implemented,
    /// it is necessary to use MemoryStream as intermediate storage.
    /// </summary>
    /// <param name="inputStream">The input stream.</param>
    /// <returns>Un-gzipped stream.</returns>
    private static Stream UnGZipSteam(Stream inputStream)
    {
        using (GZipStream gZipStream = new GZipStream(inputStream, CompressionMode.Decompress))
        {
            MemoryStream memoryStream = new MemoryStream();
            gZipStream.CopyTo(memoryStream);
            memoryStream.Position = 0;
            return memoryStream;
        }
    }

    private static void ExtractTarEntry(TarReader tarReader, string outputDirectory)
    {
        string relativePath = tarReader.FileInfo.FileName;

        // Relative path can contain slash, not backslash.
        // Use Path.GetFullPath() method to convert path.
        string fullPath = Path.GetFullPath(Path.Combine(outputDirectory, relativePath));

        switch (tarReader.FileInfo.EntryType)
        {
            case EntryType.File:
            case EntryType.FileObsolete:
                using (FileStream outputStream = File.Create(fullPath))
                {
                    // Read data from a current file to a Stream.
                    tarReader.Read(outputStream);
                }
                break;
            case EntryType.Directory:
                Directory.CreateDirectory(fullPath);
                break;
            default:
                throw new NotSupportedException("Not supported entry type: " + tarReader.FileInfo.EntryType);
        }
    }
}

Please note that since GZipStream.Position Property is not implemented, it is necessary to use MemoryStream as intermediate storage or implement GZipStream wrapper with Position property support.

TDD: Mocking System.Net.WebClient

Writing unit-test for the class that uses System.Net.WebClient, I have found out that there is no possibility to mock System.Net.WebClient using dynamic mock object frameworks (like RhinoMocks and Moq) because its methods are not virtual.

The solution is to introduce web client interface and abstract factory interface to create such web clients.

interface IWebClient : IDisposable
{
    // Required methods (subset of `System.Net.WebClient` methods).
    byte[] DownloadData(Uri address);
    byte[] UploadData(Uri address, byte[] data);
}

interface IWebClientFactory
{
    IWebClient Create();
}

The default implementations for System.Net.WebClient are straight-forward:

/// <summary>
/// System web client.
/// </summary>
public class SystemWebClient : WebClient, IWebClient
{

}

/// <summary>
/// System web client factory.
/// </summary>
public class SystemWebClientFactory : IWebClientFactory
{
    #region IWebClientFactory implementation

    public IWebClient Create()
    {
        return new SystemWebClient();
    }

    #endregion
}

Now IWebClientFactory interface can be injected as a dependency (constructor injection) and the dependent classes can be tested.

Enjoy!

FreeBSD: MonoDevelop to run NUnit tests

I have spent some hours to figure out why MonoDevelop (4.0.9, bsd-sharp) is unable to run NUnit tests on FreeBSD.
The symptom: the MonoDevelop IDE tries to run the tests and after some time interval shows that no tests were run and there are no test results.

Here is the listing of the test result (test-results directory of the test project):

<?xml version="1.0" encoding="utf-8"?>
<TestRecord xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Results>
    <UnitTestResult>
      <TestDate>2013-07-23T09:08:56</TestDate>
      <Status>Failure</Status>
      <Passed>0</Passed>
      <Errors>0</Errors>
      <Failures>0</Failures>
      <Inconclusive>0</Inconclusive>
      <NotRunnable>0</NotRunnable>
      <Skipped>0</Skipped>
      <Ignored>0</Ignored>
      <Time />
      <Message>Couldn't create a remote process.</Message>
      <StackTrace>  at MonoDevelop.Core.Execution.ProcessHostController.CreateInstance (System.String assemblyPath, System.String typeName, System.String[] addins, IList`1 userAssemblyPaths) [0x00064] in /usr/tmp/usr/ports/devel/monodevelop/work/monodevelop-4.0.9/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessHostController.cs:225 
  at (wrapper remoting-invoke-with-check) MonoDevelop.Core.Execution.ProcessHostController:CreateInstance (string,string,string[],System.Collections.Generic.IList`1&lt;string&gt;)
  at MonoDevelop.Core.Execution.ProcessService.CreateExternalProcessObject (System.Type type, IExecutionHandler executionHandler, IList`1 userAssemblyPaths) [0x0002f] in /usr/tmp/usr/ports/devel/monodevelop/work/monodevelop-4.0.9/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessService.cs:343 
  at MonoDevelop.NUnit.NUnitAssemblyTestSuite.RunUnitTest (MonoDevelop.NUnit.UnitTest test, System.String suiteName, System.String pathName, System.String testName, MonoDevelop.NUnit.TestContext testContext) [0x0003e] in /usr/tmp/usr/ports/devel/monodevelop/work/monodevelop-4.0.9/src/addins/NUnit/Services/NUnitAssemblyTestSuite.cs:387 
  at MonoDevelop.NUnit.NUnitAssemblyTestSuite.OnRun (MonoDevelop.NUnit.TestContext testContext) [0x00001] in /usr/tmp/usr/ports/devel/monodevelop/work/monodevelop-4.0.9/src/addins/NUnit/Services/NUnitAssemblyTestSuite.cs:356 
  at MonoDevelop.NUnit.UnitTest.Run (MonoDevelop.NUnit.TestContext testContext) [0x0001e] in /usr/tmp/usr/ports/devel/monodevelop/work/monodevelop-4.0.9/src/addins/NUnit/Services/UnitTest.cs:361 </StackTrace>
    </UnitTestResult>
  </Results>
  <Tests />
</TestRecord>

Furthermore, attempt to run the tests manually leads to the following output:

$ nunit-console HelloTests.dll -xmlConsole
NUnit version 2.4.8
Copyright (C) 2002-2007 Charlie Poole.
Copyright (C) 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov.
Copyright (C) 2000-2002 Philip Craig.
All Rights Reserved.

Runtime Environment - 
   OS Version: Unix 9.1.4.0
  CLR Version: 2.0.50727.1433 ( 3.1.2 (tarball Tue Jul 23 19:49:13 UTC 2013) )

Unhandled Exception:
System.ArgumentOutOfRangeException: Index is less than 0 or more than or equal to the list count.
Parameter name: index
0
  at System.Collections.ArrayList.ThrowNewArgumentOutOfRangeException (System.String name, System.Object actual, System.String message) [0x00000] in /usr/tmp/usr/ports/lang/mono/work/mono-3.1.2/mcs/class/corlib/System.Collections/ArrayList.cs:3244 
  at System.Collections.ArrayList.get_Item (Int32 index) [0x00013] in /usr/tmp/usr/ports/lang/mono/work/mono-3.1.2/mcs/class/corlib/System.Collections/ArrayList.cs:2635 
  at System.Diagnostics.ProcessModuleCollection.get_Item (Int32 index) [0x00000] in /usr/tmp/usr/ports/lang/mono/work/mono-3.1.2/mcs/class/System/System.Diagnostics/ProcessModuleCollection.cs:64 
  at System.Diagnostics.Process.get_MainModule () [0x00000] in /usr/tmp/usr/ports/lang/mono/work/mono-3.1.2/mcs/class/System/System.Diagnostics/Process.cs:228 
  at (wrapper remoting-invoke-with-check) System.Diagnostics.Process:get_MainModule ()
  at NUnit.Util.DomainManager.CreateDomain (NUnit.Core.TestPackage package) [0x0019f] in /usr/tmp/usr/ports/lang/mono/work/mono-3.1.2/mcs/nunit24/ClientUtilities/util/Services/DomainManager.cs:105 
  at NUnit.Util.TestDomain.Load (NUnit.Core.TestPackage package) [0x00011] in /usr/tmp/usr/ports/lang/mono/work/mono-3.1.2/mcs/nunit24/ClientUtilities/util/TestDomain.cs:52

Analysis:

System.Diagnostics.Process class implementation for Linux-based operating system uses procfs (/proc).
procfs is not enabled for FreeBSD by default.

Solution:

Mount procfs using /etc/fstab (reboot to apply):

proc /proc procfs rw 0 0

or mount procfs right now (without reboot):

mount -t procfs proc /proc

Since now MonoDevelop runs NUnit tests slightly!
Enjoy!

P.S. The same issue found here: FreeBSD, Mono y FireBird .Net Provider.

qmake: Adding Boost C++ libraries’ include directory

During cross-platform development using Qt you might want to use Boost C++ libraries.
It can be done simply by adding the line to the .pro file:

INCLUDEPATH += /path/to/boost_root

But it’s not right way. On another machine Boost C++ libraries may be installed into another directory.
Furthermore, if there is a SubDirs Project and all the subprojects use Boost C++ libraries, the INCLUDEPATH statement must be added into every subproject’s .pro file.

To simplify this I have done it this way.
First of all, it would be quite convenient to use either qmake variable (for example, run qmake BOOST_ROOT=/path/to/boost_root) or system environment variable (export BOOST_ROOT=/path/to/boost_root) to find Boost C++ libraries.
Here is how it looks like:

# Find Boost library.

# Try to use qmake variable's value.
_BOOST_ROOT = $$BOOST_ROOT
isEmpty(_BOOST_ROOT) {
    message(\"Boost Library\" qmake value not detected...)

    # Try to use the system environment value.
    _BOOST_ROOT = $$(BOOST_ROOT)
}

isEmpty(_BOOST_ROOT) {
    message(\"Boost Library\" environment variable not detected...)
    !build_pass:error(Please set the environment variable `BOOST_ROOT`. For example, BOOST_ROOT=c:\\boost_1_53_0)
} else {
    message(\"Boost Library\" detected in BOOST_ROOT = \"$$_BOOST_ROOT\")
    INCLUDEPATH += $$_BOOST_ROOT
}

The BOOST_ROOT qmake variable’s value is checked.
If empty, BOOST_ROOT system variable’s value is checked.

Second, to re-use this code without duplication, extract the code into common.pri file in the SubDirs’ project directory. Then, add the include () statement into subprojects .pro files, for example:

include (../common.pri)

Enjoy!

FreeBSD, QtCreator: debugging helper missing

After installing QtCreator on FreeBSD 9.1, I’ve tried debugging a simple Qt GUI application.
I set a breakpoint and started debugging. I’ve got the message:

> Debugging Helper Missing

> The debugger could not load the debugging helper library.

> The debugging helper is used to nicely format the values of some Qt and Standard Library data types. It must be compiled for each used Qt version separately. In the Qt Creator Build and Run preferences page, select a Qt version, expand the Details section and click Build All.

##Root cause:

– As stated [here](http://blog.qt.digia.com/blog/2010/04/22/peek-and-poke-vol-3/) Qt Creator’s helpers are **Python based**.
– [Python support has been introduced into gdb since gdb 7](http://docs.python.org/devguide/gdb.html#gdb-7-and-later).
– The default version of gdb (/usr/bin/gdb) is gdb 6.*. This version does not have Python support. To check it:

$ gdb
$ (gdb) python print “Hello, World!”

It must print “Hello, World!” if there is Python support.

##Solution:

1. Install [devel/gdb](http://www.freshports.org/devel/gdb). It is installed to /usr/local/bin/gdb. Also, try the Python check for this version of gdb as described above.
2. Run QtCreator, go Tools => Options => Build & Run => Kits => Debugger, use Manage… button.

Use the following settings:
– Engine: GDB Engine
– Binary: /usr/local/bin/gdb

After completing these steps, QtCreator stops at breakpoints just fine.

TCP/IP client-server application: exchange with string messages

Let’s implement simple TCP/IP client-server application which allows to exchange with string messages.

In short about TCP protocol (Wikipedia):

The Transmission Control Protocol (TCP) is one of the core protocols of the Internet protocol suite. TCP is one of the two original components of the suite, complementing the Internet Protocol (IP), and therefore the entire suite is commonly referred to as TCP/IP. TCP provides reliable, ordered delivery of a stream of octets from a program on one computer to another program on another computer. TCP is the protocol used by major Internet applications such as the World Wide Web, email, remote administration and file transfer.

So, TCP just provides the stream to send/receive bytes over the network.

The send/receive functions of socket does not guarantee that all the data you provided will be sent/received at one call. The functions return actual number of sent/received bytes.

Let’s assume the string messages will be sent as bytes (ASCII encoding). Then how to detect the end of one message?

To illustrate the problem, assume that there is two “Hello!” messages are sent.

Receiving part has the following stream:

-----------------------------------------------------------------------
| Stream bytes (ASCII)                                                |
| (chars are shown for simplicity instead of ASCII codes)             |
-----------------------------------------------------------------------
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
-----------------------------------------------------------------------
| H | e | l | l | o | ! | H | e | l | l |  o |  ! | .. | .. | .. | .. |
-----------------------------------------------------------------------

Because there is no guarantee of receiving the message at once, there is just a stream of bytes, it is necessary to use some message splitting mechanism. There are the following options:

  • Prefix the message with its size (size itself has fixed length, for example: 1 byte, 2 bytes, 4 bytes, etc.), i.e. introduce the message header.
  • Message terminator, use some byte or byte sequence to mark the end of the message.

That is why application-level protocol (see Application layer) has to be designed using one of those mechanisms to exchange with the messages.

Example

There are many approaches to design the protocol, but let’s consider the message protocol (the application-level protocol) with fixed size header (see above, first option):

----------------------------------------------------
| Number of string bytes | String bytes in ASCII   |
----------------------------------------------------
| 1 byte                 | 2 - ... bytes           |
----------------------------------------------------

There is just one byte for byte length, so the maximum string length is 255 chars.

Sending the “message”: the string should be converted to ASCII (for example) representation and sent with the byte length prefix (as described above).

Illustration:

-----------------------------------------------------------------------
| Stream bytes (ASCII)                                                |
| (chars are shown for simplicity instead of ASCII codes)             |
-----------------------------------------------------------------------
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
-----------------------------------------------------------------------
| 6 | H | e | l | l | o | ! | 6 | H | e |  l |  l |  o |  ! | .. | .. |
-----------------------------------------------------------------------

Receiving the message: receive the data to memory buffer. The process of extracting the “message” is opposite to the sending ones: receive the header (number of string bytes) and after that receive that number of bytes.

Code example

Let’s implement the client and server part of application using C#: the client will connect the server and send three messages.

Client

using System;
using System.IO;
using System.Net.Sockets;
using System.Text;

namespace NetMan.TCPIPMessenger.Client
{
    class Program
    {
        private static byte[] MessageToByteArray(string message, Encoding encoding)
        {
            var byteCount = encoding.GetByteCount(message);
            if (byteCount > byte.MaxValue)
                throw new ArgumentException("Message size is greater than 255 bytes in the provided encoding");
            var byteArray = new byte[byteCount + 1];
            byteArray[0] = (byte)byteCount;
            encoding.GetBytes(message, 0, message.Length, byteArray, 1);
            return byteArray;
        }

        public static void Main(string[] args)
        {
            const string message = "Hello, World!";
            var byteArray = MessageToByteArray(message, Encoding.ASCII);
            using (var tcpClient = new TcpClient())
            {
                tcpClient.Connect("127.0.0.1", 31337);
                using (var networkStream = tcpClient.GetStream())
                using (var bufferedStream = new BufferedStream(networkStream))
                {
                    // Send three exactly the same messages.
                    bufferedStream.Write(byteArray, 0, byteArray.Length);
                    bufferedStream.Write(byteArray, 0, byteArray.Length);
                    bufferedStream.Write(byteArray, 0, byteArray.Length);
                }
            }
        }
    }
}

Server

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace NetMan.TCPIPMessenger.Server
{
    class Program
    {
        public static void Main(string[] args)
        {
            // Create a TCP/IP listener.
            var localAddress = IPAddress.Parse("127.0.0.1");
            var tcpListener = new TcpListener(localAddress, 31337);

            // Start listening for connections.
            tcpListener.Start();

            while (true)
            {
                Console.WriteLine("Waiting for a connection...");

                // Program is suspended while waiting for an incoming connection.
                var tcpClient = tcpListener.AcceptTcpClient();
                Console.WriteLine("Client has been accepted!");

                // An incoming connection needs to be processed.
                Thread thread = new Thread(() => ClientSession(tcpClient))
                    {
                        IsBackground = true
                    };
                thread.Start();
                Console.WriteLine("Client session thread has been started!");
            }
        }

        private static bool TryReadExact(Stream stream, byte[] buffer, int offset, int count)
        {
            int bytesRead;
            while (count > 0 && ((bytesRead = stream.Read(buffer, offset, count)) > 0))
            {
                offset += bytesRead;
                count -= bytesRead;
            }

            return count == 0;
        }

        private static void ClientSession(TcpClient tcpClient)
        {
            const int totalByteBuffer = 4096;
            byte[] buffer = new byte[256];

            using (var networkStream = tcpClient.GetStream())
            using (var bufferedStream = new BufferedStream(networkStream, totalByteBuffer))
                while (true)
                {
                    // Receive header - byte length.
                    if (!TryReadExact(bufferedStream, buffer, 0, 1))
                    {
                        break;
                    }
                    byte messageLen = buffer[0];

                    // Receive the ASCII bytes.
                    if (!TryReadExact(bufferedStream, buffer, 1, messageLen))
                    {
                        break;
                    }

                    var message = Encoding.ASCII.GetString(buffer, 1, messageLen);
                    Console.WriteLine("Message received: {0}", message);
                }
            Console.WriteLine("Client session completed!");
        }
    }
}

BufferedStream Class is used to reduce the number of calls to the networking subsystem. Buffers improve read and write performance (in this case, receive and send).