PETZOLD BOOK BLOG

Charles Petzold on writing books, reading books, and exercising the internal UTM


Recent Entries
< PreviousBrowse the ArchivesNext >
Subscribe to the RSS Feed

Windows 8 XAML Files and C++ Header Files

December 19, 2012
New York, N.Y.

Programmers returning to C++ after spending some years with C# are likely to have forgotten a few basics, or might not quite grasp how XAML fits in with the big picture. That's certainly the case for me as I'm becoming multilingual in Windows 8 programming! Here's an example of something that has gotten me several times.

Perhaps you want a Slider in the center of your Windows 8 page, so you put it in the XAML file:

<Page x:Class="SliderDemo.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="using:SliderDemo">

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <Slider VerticalAlignment="Center"
                Margin="50 0" />
    </Grid>
</Page>

This is the same for C# or C++. But as you're experimenting with this Slider, you realize that the tooltip is not right. The tooltip displays the value of the Slider between 0 and 100, but within your code you're actually going to be using the base-10 logarithm of the Slider value, and it would be great if the tooltip displayed that value.

No problem. All you need is a value converter, which is a class that implements the IValueConverter interface. This class can be as generalized or as ad hoc as you'd like. If you're doing it in C++, here's the header file for a LogConverter class:

#pragma once

namespace SliderDemo
{
    public ref class LogConverter sealed : Windows::UI::Xaml::Data::IValueConverter
    {
    public:
        virtual Object^ Convert(Platform::Object^ value, 
                                Windows::UI::Xaml::Interop::TypeName targetType, 
                                Platform::Object^ parameter, 
                                Platform::String^ language);

        virtual Object^ ConvertBack(Platform::Object^ value, 
                                    Windows::UI::Xaml::Interop::TypeName targetType, 
                                    Platform::Object^ parameter, 
                                    Platform::String^ language);
    };
}

And here's the code:

#include "pch.h"
#include "LogConverter.h"

using namespace SliderDemo;

using namespace Platform;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Interop;

Object^ LogConverter::Convert(Object^ value, TypeName targetType, 
                              Object^ parameter, String^ langauge)
{
    wchar_t result[10];
    swprintf(result, 10, L"%0.2f", log10((double)value));
    return ref new String(result);
}

Object^ LogConverter::ConvertBack(Object^ value, TypeName targetType, 
                                  Object^ parameter, String^ language)
{
    return value;
}

To persuade the Slider to use this value converter for displaying the value in the tooltip, you set the ThumbToolTipValueConverter property to an instance of this class. Often the value converter is instantiated as a XAML resource, but you can alternatively reference it directly in the Slider markup. Notice the local XML namespace prefix:

<Page x:Class="SliderDemo.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="using:SliderDemo">

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <Slider VerticalAlignment="Center"
                Margin="50 0"
                Minimum="1">
            <Slider.ThumbToolTipValueConverter>
                <local:LogConverter />
            </Slider.ThumbToolTipValueConverter>
        </Slider>
    </Grid>
</Page>

If you're coding in C#, you're done. But when you try to build this C++ program, you get two errors:

The first error is apt to cause you to believe that something is wrong with the definition of the LogConverter class. But that's not the case. Both these errors reference a statement in the xamltypeinfo.g.cpp file, which is a statement that instantiates LogConverter. That "g" in the filename means this file is "generated" during the build process, and that's apt to be also baffling, because there's nothing you can do with this file directly. But obviously xamltypeinfo.g.cpp has no knowledge of this LogConverter class.

Fortunately, xamltypeinfo.g.cpp contains #include statements for both App.xaml.h and MainPage.xaml.h, so the simple solution is to put an #include statement for LogConverter.h in one of these two header files:

#include "LogConverter.h"

I often put such an #include statement in MainPage.xaml.h if the class is referenced only in the MainPage.xaml file, but if you're referencing such a class in multiple XAML files, putting it in App.xaml.h would make more sense.

At any rate, that's the lesson: If a custom class is referenced only in a XAML file and not in a code file, an #include statement for the class's header file is still required to accomodate the code generated during the build process.


Comments:

It's too bad the Windows guys won the Win8 design war (instead of the dev div guys). Instead of providing multilingual access, they should have integrated the .NET CLR deeply in Win8 (and especially Win8RT).

Then we could all throw our C++ books in the trash, where they belong.

No offense. I know you're just going with the flow. It's just a shame.

— Matt, Sat, 22 Dec 2012 22:55:09 -0500

From a theoretical perspective, managed platforms and managed languages are great, and I remain very much in favor of them. But in the real world, certain applications involving graphics and audio require squeezing maximum performance from the machine, and for those applications you want to use C++ and DirectX.

Programming is an engineering discipline and must transcend ideology. — Charles

Thank you For Code

amixer, Tue, 25 Dec 2012 23:30:18 -0500

Someone named Felix9 has a number of posts that point to Microsoft job postings that say explicitly that they're working on updating the C++ and C# compilers (Roslyn clearly isn't just about exposing the compiler's syntax tree) to bring C++ optimization techniques to C#, thus making C# even more performant.

See, for example, http://channel9.msdn.com/Forums/Coffeehouse/MS-working-on-a-same-compiler-for-C-AND-C--Not-in-incubation-but-for-production-

— Larry Smith, Thu, 27 Dec 2012 11:17:14 -0500

Charles,

I thank you for continuing to make an effort to show us how to use windowsRT and new features of windows 8 via C++

While I can understand that some people think that C++ is out dated (which is not true, is alive and kicking (e.g. C++11, C++ books, C++ amp, Channel 9 msdn C++...) , you continue working hard to show both C# and C++.

I do understand that C and/or C++ can be difficult for some people, you are right. We need it for high-demanding applications. No compiler optimization can replace native code of C++. Besides, someone (Bjarne) said that leaving garbage around (Java, C# Garbage Collection) is just bad manners.

In another note, I notice that the hard copy of Programming Windows was moved to Feb, 2013. I do have the pdf copy I purchased and I assume that I will have the full pdf soon once is ready. But nothing like hard copy...

Thank you Charles.

Francisco, Fri, 28 Dec 2012 11:10:14 -0500

Thanks! I should have an exciting announcement for Windows 8 C++ programmers in just a few days. — Charles

Thanks! I'd be interested , C# and C++ both are great tool and everything to me to develop much of the windows programs

— Anoop Chauhan, Sun, 30 Dec 2012 00:40:30 -0500

as an old student of yours that have bought all of your books except the .net ones i really really hope that a c++ version of the book is a possibilty.

— Asehea, Mon, 31 Dec 2012 14:06:51 -0500

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Button Click="button_Click">OK</Button>
    <x:Code>
    <![CDATA[
        void button_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }
    ]]>
    </x:Code>
</Window>

The above code can not be parsed by XAML cruncher.

Error is:

XAMLReader: Must compile XAML file that specifies event.

What do I need to do?

— Nilesh, Thu, 3 Jan 2013 02:25:12 -0500

Please keep blog comments on topic. That's some WPF XAML you've got there.

The XamlReader.Load method cannot parse XAML that contains code, as is mentioned on page 470 of Applications = Code + Markup. Either move that markup into a Visual Studio project and compile it, or put the code in a C# file, and compile the code and markup together in Visual Studio.

— Charles

I think there are significant enough differences between the C# and C++ versions of any Windows 8 XAML app to make switching to C++ quite compelling.

We have a C# app in the app store which suffers from garbage-collection slowdown if you perform a lot of speedy complex navigation between XAML pages on low-powered ARM devices (Surface).

We created a test copy of the app in c++ and the performance is significantly better, and animations much smoother. We had already optimised and profiled our C# app, so we know there are no errors. We are currently re-writing the app fully in c++, but going through the pain of climbing the steep learning curve

Dean Chalk, Mon, 28 Jan 2013 07:54:14 -0500

Dean Chalk,

It's good to hear real world experience with the two languages. Thanks for your input!

And thanks, Charles, for the great work you've done over the years! I'm sure MANY programmers feel the same way!

Jim Kay, Tue, 30 Jul 2013 13:02:45 -0400


Recent Entries
< PreviousBrowse the ArchivesNext >
Subscribe to the RSS Feed

(c) Copyright Charles Petzold
www.charlespetzold.com