Category Archives: .net

End of Project Notes

In October of 2007 I started work on a project to convert and extend an older True BASIC data processing program. Early this year, after releasing several versions, work on this project ended and I thought it would be interesting to share some thoughts and experiences. I do not consider myself a ‘master programmer’ and these notes are not intended as ‘expert guidance’ – so why post them? Because I have enjoyed similar posts from other programmers!

Overview:

Platform: The requested target for the project was a Windows desktop application. Windows desktop applications do not get much love/hype these days and at various times during the project we talked about doing a web version. But with no existing server/host to use and without manpower/budget to acquire and maintain a server/host a desktop application was a good choice. Application installation and updates can be a challenging part of a desktop application – but in this case we only ran into a few support issues and it was really not a problem.

Programming Language/Platform: C#/.NET (eventually 3.5)/Visual Studio (eventually 2010). Since Windows desktop was the target and we had existing experience with this stack we did not seriously consider other choices…

Gui: We started the project in WinForms and later moved to WPF. The WinForms version worked fine, but I find WinForms hard to love – in particular I dislike the GUI designer and generated code. It was refreshing to move to WPF, working with XAML for the UI is quite nice and I have found WPF to be a quicker, easier and more maintainable way to create UI (I have used WPF for several other projects as well). I would hesitate to start a new project in WinForms – but I have started to strongly suspect that UI technology/framework matters less than I would have guessed several years ago. My personal experience has been that many technologies have reasonable basic functionality – you are going to be able to get a decent/basic UI built without too much time/pain. But it seems like that in every technology it is going to cost quite a bit of time to tweak/create/craft all of the details needed to make the UI something you would actually want to use (UI hints to help users solve their problems, help for beginners, understandable error messages, good editing, great validation, smart interaction with the database, attractive visuals, great layout, etc…). WPF seems like a step forward compared to WinForms – but not a big enough step forward to make creating good UI easy or to make achieving your vision uncomplicated… I would pick WPF over WinForms for a new project – but certainly not with the illusion that a great UI can be created quickly in any technology.

Data: We used Microsoft SQL Server Express for this project (2005 and 2008 versions). For this project a carefully constructed schema helped us to enforce rules about the data, catch errors and query the data much more easily than a non-relational store would have. We did 95% of our data processing with SQL queries – for this project that turned out to be a very pleasant way to work.

Version Control System: We started this project in 2007 and used Subversion and Trac at hosted-projects.com. While I currently do not have much love for Subversion I did realize after switching to Mercurial that it is easier to explain, understand and use for simple scenarios – a great benefit in some situations. About two years into the project we moved to Mercurial and Assembla. Mercurial is fantastic – my experience has been that Mercurial has quite a few benefits (easier check-ins, faster access to history, nicer branch/merge, quick cloning of the entire repository for experiments) without any additional hassles once you get over the initial learning curve. We stayed with Mercurial for the rest of the project but did move from Assembla to Fogbugz and Kiln. Moving to FogBugz was nice – we found that the default FogBugz setup worked better for us than a default Trac setup (we were not interested in spending time customizing Trac). Moving to Kiln was FANTASTIC – I love the features that Kiln provides for working with Mercurial repositories. The ability to maintain and organize multiple repositories made it much easier to work simultaneously on different releases and features. We took advantage of the 2-person Student/Start-up (free) plan. I really like FogBugz and Kiln, but I do wish they had some additional pricing options – while these services are certainly ‘worth’ $30 per person per month that could be tough to justify for smaller/experimental/less profitable endeavors with more than two developers.

Details:

LINQ to SQL – For a simple strongly typed data access this was great! Creating the data layer via SqlMetal on the command line was a nice part of our workflow. But I am very glad that we did not try to do all of our data processing via LINQ – when we experimented with trying to do everything in LINQ we quickly found that complex queries were more readable, easier to create and faster to change done directly in SQL. While LINQ to SQL is still supported by Microsoft I think it is fair to say all their energy is going into the ADO.NET Entity Framework and I don’t think I would choose LINQ to SQL for a new project.

SQL Server Compact – As noted above we ended up going with SQL Server Express – but our original intention was to use SQL Server Compact edition as the primary database and include an option for advanced users to use an existing SQL Server instance. Unfortunately my ignorance killed the SQL Server Compact part of our plans – I was developed for months via Sql Server and had written hundreds of lines of SQL before I realized that some of the syntax that I had used was not available in SQL Server Compact edition. At that point we felt it would have taken too much time to rewrite the SQL and we went forward with just SQL Server Express. This was a learning experience for me about the differences in SQL databases…

Importing Data – We, of course, ran into problems with users supplying invalid data – but I think that is always true of user input. The more interesting problem we ran into was that we underestimated the user’s ability to understand and fix the problems in their data. For the second version we added a validation layer that gave us a chance to both catch errors in the data AND give the user detailed/helpful error messages – it was certainly not perfect but it helped quite a bit to have detailed user targeted error messages.

Conclusion:

Like any project if I was going to do this again I could do a better job – but we managed to produce a working application that we were able to maintain and constantly improve for several years! I think most of our choices were reasonable given the goals and resources – but certainly database and desktop application would be two things that I would consider carefully if were starting again from the beginning.

CM

Advertisements

Generating WPF with T4 Templates for Localization

Recently I had the opportunity to explore setting up a small WPF application for globalization/localization. I had no previous experience with this process, so I started by doing some searching and reading. I thought the links below were particularly interesting:

WPF Localization Guidance – Included in this project is The WPF Localization Guidance PDF by Rick Strahl and Michele Leroux Bustamante – I highly recommend reading this! Great details, several approaches are examined.

Creating an Internationalized Wizard in WPF by Josh Smith, Karl Shifflett. Very nice walk thru of building an Internationalized Wizard style app with resource files. This is a very approachable place to start.

WPF Multi-Lingual at Runtime by Andrew Wood – A XmlDataProvider based solution.

Localizing WPF Applications using Locbaml by brunzefb – This link is notable for its comparison of several different approaches.

WPF Localization by Sacha Barber – Interesting because of the third method shown in the article that uses ResourceDictionaries. For more information on using Resource Dictionaries see the answer to this question on Stack Overflow by  Ray Burns.

 

One interesting thing about many of the approaches above is that the focus seems to on localizing strings/text, and to a lesser degree settings, images and other resources. In the context of WPF I was surprised not to find more information about customizing the layout of the UI as part of the translation into another language. I think the structure of XAML encourages a UI composed of many elements that will need more than string substitution to be ideal in another language.

For example, the XAML below and UI it generates seems typical of the kind of composition and ‘richness’ encouraged by WPF/XAML’s structure and tools:

<UserControl
		xml:lang="en"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="basic_styles.xaml" />
                <ResourceDictionary Source="equations.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>

	<WrapPanel Style="{StaticResource description_wrap_panel_style}">

		<TextBlock	x:Name="c_textblock"
					Style="{StaticResource description_textblock_style}"
					AutomationProperties.Name = "Enter a Constant, C, that satisfies the following equation: the standard error of the estimate is equal to the constant C over the square root of the sample size">
			Enter a constant, <Italic>C</Italic>, that satisfies
    	<InlineUIContainer Style='{StaticResource image_container_style}'>
    		<Image x:Name='formula_11'
					Source='{StaticResource equation_11}'
					Style='{StaticResource image_style}'>
                <Image.Height>
                    <MultiBinding Converter='{StaticResource image_size}'>
                        <Binding Mode='OneWay'
								ElementName='formula_11'
								Path='Tag'/>
                        <Binding Mode='OneWay'
								ElementName='c_textblock'
								Path='FontSize'/>
                    </MultiBinding>
                </Image.Height>
            </Image>
    	</InlineUIContainer>
	    </TextBlock>

		<TextBlock 	Style="{StaticResource description_textblock_style}"
					KeyboardNavigation.TabIndex="1">
			(<Hyperlink AutomationProperties.Name='More information about the constant C' x:Name='c_hyperlink'>more info</Hyperlink>)
		</TextBlock>

		<TextBox 	Style="{StaticResource entry_textbox_style}"
					AutomationProperties.LabeledBy="{Binding ElementName=c_textblock}"
					KeyboardNavigation.TabIndex="0">
		</TextBox>

	</WrapPanel>
</UserControl>

Certainly changing out all of the strings to translate this example is possible (slightly painful because of the number of string to change out…). In French or Spanish this would work fine:

 

 

However, here is the same UI translated into Japanese – notice that the translator did not keep the elements in the same position.

 

To accommodate a flexible layout in this application I decided to use T4 templates to generate ‘loose’ XAML files. These files are included in the output and parsed at runtime based on the CurrentCulture.

The code below is the contents of the file base_block.tt – this t4 template holds the common elements of the XAML files and will be ‘imported’ by the language specific t4 templates. The language specific templates will provide values for the variables introduced in base_block.tt. One important detail is the use of encoding="Unicode" – I assumed “Utf-8” would work but the XamlParser would error on some characters when the template specified Utf-8, apparently because of the BOM setting…

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".xaml" encoding="Unicode"#>

<UserControl
		xml:lang="<#= this.xml_lang #>"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="basic_styles.xaml" />
                <ResourceDictionary Source="equations.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>

	<WrapPanel Style="{StaticResource description_wrap_panel_style}">

		<TextBlock	x:Name="c_textblock"
					Style="{StaticResource description_textblock_style}"
					AutomationProperties.Name = "<#= this.textblock_automation_name #>">
			<#= this.textblock_constant_C_contents #>
	    </TextBlock>

		<TextBlock 	Style="{StaticResource description_textblock_style}"
					KeyboardNavigation.TabIndex="1">
			<#= this.hyperlink_textblock_contents #>
		</TextBlock>

		<TextBox 	Style="{StaticResource entry_textbox_style}"
					AutomationProperties.LabeledBy="{Binding ElementName=c_textblock}"
					KeyboardNavigation.TabIndex="0">
		</TextBox>

	</WrapPanel>
</UserControl>

<#+

	private string xml_lang = @"";
	private string textblock_constant_C_contents = @"";
	private string textblock_automation_name = @"";
	private string hyperlink_textblock_contents = @"";

#>

Note that the variables hold all of the information that I wanted to be able to manipulate – not just the string portions of the UI. The file for English, en.tt:

<# 
	
	xml_lang = @"en";

	textblock_constant_C_contents = 
		@"Enter a constant, <Italic>C</Italic>, that satisfies
    	<InlineUIContainer Style='{StaticResource image_container_style}'>
    		<Image x:Name='formula_11' 
					Source='{StaticResource equation_11}' 
					Style='{StaticResource image_style}'>
                <Image.Height>
                    <MultiBinding Converter='{StaticResource image_size}'>
                        <Binding Mode='OneWay' 
								ElementName='formula_11' 
								Path='Tag'/>                        
                        <Binding Mode='OneWay' 
								ElementName='c_textblock' 
								Path='FontSize'/>
                    </MultiBinding>
                </Image.Height>
            </Image>
    	</InlineUIContainer>";

	textblock_automation_name = @"Enter a Constant, C, that satisfies the following equation: the standard error of the estimate is equal to the constant C over the square root of the sample size";

	hyperlink_textblock_contents = @"(<Hyperlink AutomationProperties.Name='More information about the constant C' x:Name='c_hyperlink'>more info</Hyperlink>)";

#>

<#@ include file="base_block.tt" #>

The file for the Spanish version:

    <#
	
        xml_lang = @"es";

        textblock_constant_C_contents =
            @"Ingrese una constante, <Italic>C</Italic>, para resolver
            <InlineUIContainer Style='{StaticResource image_container_style}'>
                <Image x:Name='formula_11'
                        Source='{StaticResource equation_11}'
                        Style='{StaticResource image_style}'>
                    <Image.Height>
                        <MultiBinding Converter='{StaticResource image_size}'>
                            <Binding Mode='OneWay'
                                    ElementName='formula_11'
                                    Path='Tag'/>
                            <Binding Mode='OneWay'
                                    ElementName='c_textblock'
                                    Path='FontSize'/>
                        </MultiBinding>
                    </Image.Height>
                </Image>
            </InlineUIContainer>";

        textblock_automation_name = @"Ingrese una constante, C, que satisface la siguiente ecuación: el error estándar de la estimación es igual a la constante C sobre la raíz cuadrada del tamaño de la muestra.";

        hyperlink_textblock_contents = @"(<Hyperlink AutomationProperties.Name='Más información acerca de la constante C'>más información</Hyperlink>)";

    #>

    <#@ include file="base_block.tt" #>

Each of the XAML files has a Build Action of ‘Content’ so that it is included in the output for the project.  At runtime I look at the CurrentCulture, compare that to the names of the generated XAML files that are available, feed the file to XamlReader.Load() and add the resulting UserControl into the UI as needed. A small sample app demonstrating this is a available here.

 

I do not have enough experience with globalization/localization to be confident this approach would work in all situations, but for this application it did work and I enjoyed that it: easily allows flexible UI layout, generated XAML files that could be viewed in the VS editor and is simple to use. I seems to me that the biggest downsides to this approach are that it does not allow translators to work on a simple value pair style file and the loose XAML does not allow for a code-behind (which is usually fine but occasionally awkward – at least for me). I would love to hear any comments or feedback on this approach!

 

Special thanks to Lance and Kent for translating for me!! And extra thanks to Lance for pointing out how to cleanly post source code on WordPress.com

 

Enjoy!

CM

Mercurial and White Presentations

I recently had the opportunity to do two presentations at a Tucson .NET User Group meeting – Aaron Wagner and I gave a ~40 minute presentation on Mercurial and I did a short presentation on White!

It was a privilege to have the opportunity to share information about these tools and great to get some extra motivation to keep learning. The Mercurial presentation was 2/3 slides and 1/3 live demo (Mercurial/TortoiseHg and Kiln) targeted at providing a basic introduction to Mercurial. I have put the slides here for download (Creative Commons Attribution-Share Alike 3.0 Unported), if you are doing a similar short presentation they may be useful – if you are just looking for tutorials/information about Mercurial I suggest you skip these slides and look at this tutorial and this book – both great starting points. (Powerpoint and Impress files are included in the download – the Impress file is not ideal but should be clean enough to easily use or copy).

Enjoy!

CM