Archive for the ‘csharp’ Category.

Loading rich text file links in a browser from a WPF Navigation Application

Previously, I discussed loading a rich text file in a regular WPF Application in this post.
Loading a RichTextBox from an RTF file using binding or a RichTextFile control

UPDATE: If you use the new version of RichTextFile located at this link, then you don’t even need to do this.

The following use cases must be met:

  1. Load and display a rich text file in read only mode
  2. The links must open inside a browser and not in the application

We created a RichTextFile control that inherits RichTextBox and configured it to support binding. Now we are going to use this same object in a WPF Navigation Application.

A WPF Navigation Application is going to react differently. Links are going work by default, so the Hyperlink.Click event doesn’t have to be used. However, there is a problem, the links open in the actual application’s window and not in a browser. Lets fix this.

Part 2 – Using the RichTextFile class in a WPF Navigation Application

Use Case 1 – Loading a rich text file

Create a new WPF Application in Visual Studio.

Add a Frame element and set the source to RTF.xaml, which we will create next.

<Window x:Class="RichTextFileTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Frame Source="RTF.xaml" />
    </Grid>
</Window>

There is no code behind for this, yet.

Create a new WPF Page called RTF.xaml.

Add the above RichTextFile object to the project.

Add an xmlns reference to our new object. Then add our new object. Notice in our new object that we set IsReadOnly=”True” but we also set IsDocumentEnabled=”True”. This allows for clicking a link even though the document is read only.

<Page x:Class="RichTextFileTest.RTF"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"
      Title="RTF"
      xmlns:controls="clr-namespace:System.Windows.Controls">
    <Grid>
        <controls:RichTextFile File="{Binding File}" IsReadOnly="True" IsDocumentEnabled="True"/>
    </Grid>
</Page>

Code Behind

using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;

namespace RichTextFileTest
{
    /// <summary>
    /// Interaction logic for RTF.xaml
    /// </summary>
    public partial class RTF : Page
    {
        public RTF()
        {
            InitializeComponent();
            Example example = new Example() { File = "File.rtf" };
            DataContext = example;
        }
    }

    public class Example
    {
        public String File { get; set; }
    }
}

Now the first use case is complete, the rich text file is loading into the RichTextFile control and is visible in the application. However, the second use case is incomplete, but not because the links aren’t loading, but because they are not loading in a browser. Instead they are loading inside the Frame element.

Use Case 2 – Getting the links to open in a browser

Getting the links to open in a browser is not straight forward and it took me quite some time to find an easy solution. Somehow, the link must be open in a browser and then the Navigation event must be canceled.

The easiest way to do this is to implement the Nagivating function on the Frame element in our MainWindow.

<Window x:Class="RichTextFileTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Frame Source="RTF.xaml" Navigating="Frame_Navigating"/>
    </Grid>
</Window>

Now implement the code behind for the Frame_Navigating method.

using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;

namespace RichTextFileTest
{
    /// <summary> 
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Frame_Navigating(object sender, System.Windows.Navigation.NavigatingCancelEventArgs e)
        {
            Frame frame = sender as Frame;
            if (frame != null && frame.Source != null)
            {
                // See if we are hitting a link using HTTP or HTTPS
                if (frame.Source.ToString().StartsWith("http://", System.StringComparison.CurrentCultureIgnoreCase)
                    || frame.Source.ToString().StartsWith("https://", System.StringComparison.CurrentCultureIgnoreCase))
                {
                    // Open the URL in a browser
                    Process.Start(frame.Source.ToString());

                    // Cancel the Navigation event
                    e.Cancel = true;
                }
            }
        }
    }
}

The links should now be opening in your browser and not in your application.

Here is the sample project that demonstrates this.
RichTextFileNavigation.zip

Loading a RichTextBox from an RTF file using binding or a RichTextFile control

Sometimes you have a rich text document that exists as an actual file and you simply want to load the file and display it.

My exact use cases are these:

  1. Load and display a rich text file in read only mode
  2. The links must open inside a browser and not in the application

I like to use MVVM, so my goal is to use binding to pass in the file name. Unfortunately the RichTextBox class is not designed to bind to a file name. However, extending this control to have this functionality is quite easy.

RichTextFile extending RichTextBox

Here is my new class. I have extended RichTextBox with four additional items in a new derived class called RichTextFile.

  1. Added a String Property called File.
  2. Added a DependecyProperty called FileProperty
  3. Added a PropertyChangedCallback function called OnFileChanged
  4. Added a ReadFile function that reads a .rtf file into a FlowDocument
  5. Added a Constructor that adds a handler for the Hyperlink.RequestNavigateEvent.
  6. Added a Property called OpenLinksInBrowser.
using System.Diagnostics;
using System.IO;
using System.Windows.Documents;

namespace System.Windows.Controls
{
    internal class RichTextFile : RichTextBox
    {

        public RichTextFile()
        {
            AddHandler(Hyperlink.RequestNavigateEvent, new RoutedEventHandler(HandleHyperlinkClick));
        }

        private void HandleHyperlinkClick(object inSender, RoutedEventArgs inArgs)
        {
            if (OpenLinksInBrowser)
            {
                Hyperlink link = inArgs.Source as Hyperlink;
                if (link != null)
                {
                    Process.Start(link.NavigateUri.ToString());
                    inArgs.Handled = true;
                }
            }
        }

        #region Properties
        public bool OpenLinksInBrowser { get; set; }

        public String File
        {
            get { return (String)GetValue(FileProperty); }
            set { SetValue(FileProperty, value); }
        }

        public static DependencyProperty FileProperty =
            DependencyProperty.Register("File", typeof(String), typeof(RichTextFile),
            new PropertyMetadata(OnFileChanged));

        private static void OnFileChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            RichTextFile rtf = d as RichTextFile;
            if (rtf == null)
                return;

            ReadFile(rtf.File, rtf.Document);
        }
        #endregion

        #region Functions
        private static void ReadFile(string inFilename, FlowDocument inFlowDocument)
        {
            if (System.IO.File.Exists(inFilename))
            {
                TextRange range = new TextRange(inFlowDocument.ContentStart, inFlowDocument.ContentEnd);
                FileStream fStream = new FileStream(inFilename, FileMode.Open, FileAccess.Read, FileShare.Read);

                range.Load(fStream, DataFormats.Rtf);
                fStream.Close();
            }
        }
        #endregion
    }
}

You can use this new object to load a .rtf file quite easily. I am going to show you how I am succeeding in my two use cases using both a regular WPF Application and a WPF Navigation Application.

Part 1 – Using the RichTextFile class in a WPF Application

Use Case 1 – Loading a rich text file

Create a new WPF Application in Visual Studio.

Add the above RichTextFile object to the project.

Add an xmlns reference to our new object. Then add our new object. Notice in our new object that we set IsReadOnly=”True” but we also set IsDocumentEnabled=”True”. This allows for clicking a link even though the document is read only.

<Window x:Class="RichTextFileTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        xmlns:controls="clr-namespace:System.Windows.Controls">
    <Grid>
        <controls:RichTextFile File="{Binding File}" IsReadOnly="True" IsDocumentEnabled="True" />
    </Grid>
</Window>

Code Behind

using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Documents;

namespace RichTextFileTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Example example = new Example() { File = "File.rtf" };
            DataContext = example;
        }
    }

    public class Example
    {
        public String File { get; set; }
    }
}

Now the first use case is complete, the rich text file is loading into the RichTextFile control and is visible in the application. However, the second use case is incomplete as clicking the link does nothing.

Use Case 2 – Getting the links to open in a browser

The links can easily made to open in a browser now by simply setting OpenLinksInBrowser=”True” on the RichTextFile object.

<Window x:Class="RichTextFileTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        xmlns:controls="clr-namespace:System.Windows.Controls">
    <Grid>
        <controls:RichTextFile File="{Binding File}" IsEnabled="True" IsReadOnly="True" IsDocumentEnabled="True" OpenLinksInBrowser="True"/>
    </Grid>
</Window>

The links should now be opening in your browser.

Here is the sample project that demonstrates this.
RichTextFileTest.zip

Part 2 – Using the RichTextFile class in a WPF Navigation Application

How to get a job in software development in as little as 6 months

Hello. I keep hearing about the number of unemployed.  Many have been unemployed for more than 6 months and are likely to be unemployed for another 6 months.

Well, technology is not going away so here is a solution for some of you.

Many of you think that you need a degree in Computer Science to become a Software Developer.  This is just not true.  Many of the Software Developers that I know do not have a degree in Computer Science.  However, most love technology and so they learn it on their own.

If you love technology and you can learn on your own, you could become a Software Developer in 6 months.

While this article is for Software Development, the pattern I describe here work with IT as well, and many other careers in many fields.

Disclaimer: I can’t promise that everyone who does this method will succeed in 6 months, but at least it is a pattern that you can try. And if you end up getting a job outside of technology the skills you learned here will still be beneficial for the rest of your life as computers are likely to still be here well past your retirement.

Month 1

Step 1 – Get access to a computer and the internet

Yes you need a computer to become a software developer.  You even need one to study. You need the internet to have access to the nearly unlimited amount of free training material about development.

Step 2 – Choose one of the top programming languages

The top languages for writing code today and probably will continue to increase in popularity in the future are these:

  • Java
  • PHP
  • C# or ASP.NET

Other languages that are popular are C++, Objective C, Perl, Python, etc…

Web development is fun too. HTML, CSS, JavaScript, etc. One language that is likely to become more popular now and in the near future are HTML5. You have probably heard buzz about it.

However, these are no the only languages you could learn.

Maybe you would like to work with databases. You could learn to about SQL.  There are many databases to choose from, the top being these:

  • MySQL
  • MS SQL
  • Oracle
  • PostgreSQL

Maybe you are into business technology. You could become an expert at a specific piece of software, such as how to create business intelligence reports with QlikView. There are hundred of products that require technology experts to use them and specializing in any one of them could lead to a stable career.

Step 3 – Find the Certification Preparation material

Here are some of the Certifications for the common languages.

Here is a list of certification sites for database software.

Many software applications have certification as well. You can find these certifications with a simple search on the internet.

Once you have the certification material, there should be some information on what to study and what to learn to complete the certification. It is your goal to pass a certification in 6 months.

Step 4 – Download any free or trial software

Almost all software has either open source, or a shareware, express, or trial versions of their software that you can use for free.  Sometimes, like in the case of trial software, there is a time limit.  But that doesn’t prevent you from learning as much as you can before the trial expires.

To become a developer, one of the most basic tools is an Integrated Development Environment (IDE).  Here is a list of the free or open source IDEs you can get.

You can find free or open source version of other software for other languages with a simple search on the internet.

With this free software you are set free to practice as you learn.

Step 5 – Access the free documentation and training on the internet

There are a lot of free tutorials, videos, blog posts and more on the internet.  You can become an expert in something without ever buying a book or paying from a training class.

The following site has a quick tutorial on almost all programming languages: http://www.w3schools.com/

You can use this information to study and prepare for your certification.

Make a list of all the tutorials you have found and that you plan to study. Put this in a spreadsheet in a nice way, maybe a separate line for each chapter or section, so you can see your progress.  If you want, email the spread sheet and I will post it for the next person.

Month 2 – 3

Study and practice. You now ave all the software you need and all the training material you need.  Go through it.  This takes time.

Do the sample development projects, don’t just look at them, code them up, compile them, and run them.

Month 4

Step 1 – Pick a development project and work on it.

There are so many open source projects in the world and you can pick any of them. Or you can start your own. Or maybe you have an idea for some software that you can sell and you can start your own business. Whatever, just pick something and start working on it.

Here is a good way to figure out what project to choose.

  1. Ask yourself, what interests me outside of development? (Maybe you are a mechanic and you tinker with cars, or maybe you like to collect stamps, or maybe you like horses)
  2. Is there an open source software project in this area? If not, is there an opportunity to create one? Or better yet, is there a software opportunity that could inspire a small business in this area.

Another option, if you have any connections with any company at all, offer to do something to help their company for free.  Maybe your hair stylist needs you to develop something to help her with her clients.  Even though you are doing it for free, you are writing code that will go into production in a business environment.  This experience is invaluable.

Step 2 – Keep learning

As you start working on this project, you will start using what you have already learned. However, you aren’t done learning. And you will have to solve some tough problems. Keep learning.

Month 5

Step 1 – Schedule the certification exam you have chosen for the end of the month

Keep learning. Keep working on your development project. However, take some time to focus on the certification exam. Find practice tests, sample question.

Most people fail the exam on the first try.  This is why you are taking it once in Month 5.

Step 2 – Start the job hunt

Start looking for companies that are hiring Jr. Developers or entry-level developers in your position.

Add to your resume all that you have done, your project, you training, your certification if you passed it.

Month 6

Keep up the job hunt.

If you didn’t pass the certification in Month 5, repeat month 5 steps.

Take the first job you can get, no matter the pay. You are on your way to becoming an experience developer.

Month 7 and later

Keep it up.  Just because you didn’t quite make it 6 months doesn’t mean the work you have done isn’t valuable and isn’t going to pay off.

Still not passing the certification exam. Don’t worry, these test are hard and I know people who understand the technology of a certification that still fail multiple times.  Keep trying.

The long term career

Developers with 1-3 years experience can make 38k to 59k. With 4-8 years experience they can make 60 to 80k. And if you have worked hard to become a senior developer, your salary can skyrocket towards 6 figures and beyond.

 

Software Business Ideas

There are many ideas for starting a business and I have a nice list myself. If you are interested in an idea that you think could become a successful selling piece of software, I am will to help you an consult with you.  Just hit me up on the contact page.

Not into development?

Trying applying this pattern other careers. I think you find it works for many other career paths as well.  This could also apply to the medical field, housing market, and many other fields.

 

 

String extension methods

Here is a list of string extension methods. If you know of any more cool extension methods, please comment.

using System;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Security;

namespace LANDesk.Install.Common.Extenders
{
    /// <summary>
    /// This class adds methods to String that are useful
    /// </summary>
    public static class StringExtender
    {
        #region DLL Imports
        [DllImport("ldmsinst.dll", CharSet = CharSet.Ansi, EntryPoint = "Decrypt", CallingConvention = CallingConvention.Cdecl)]
        public static extern void Decrypt(int pwdLen, byte[] pwd);

        [DllImport("ldmsinst.dll", CharSet = CharSet.Ansi, EntryPoint = "Encrypt", CallingConvention = CallingConvention.Cdecl)]
        public static extern void Encrypt(int length, byte[] data);
        #endregion

        /// <summary>
        /// This adds a function to a string object that will convert the string
        /// to a SecureString.
        /// </summary>
        /// <param name="password">The string to convert to a secure string.</param>
        /// <returns>SecureString</returns>
        public static SecureString ConvertToSecureString(this string password)
        {
            SecureString ss = new SecureString();
            if (password == null)
                throw new ArgumentNullException("password");

            foreach (Char c in password)
            {
                ss.AppendChar(c);
            }
            return ss;
        }

        /// <summary>
        /// Checks if the string contains any of a list of characters
        /// entered as a string.
        /// </summary>
        /// <param name="password">Any string.</param>
        /// <param name="listofcharacters">Any string representing a list of characters.</param>
        /// <returns>bool</returns>
        public static bool ContainsAnyOf(this string password, char[] listofcharacters)
        {
            foreach (char c in listofcharacters)
            {
                if (password.Contains(c.ToString()))
                    return true;
            }
            return false;
        }

        /// <summary>
        /// Checks if the string contains any of a list of characters
        /// entered as a string.
        /// </summary>
        /// <param name="password">Any string.</param>
        /// <param name="listofcharacters">Any string representing a list of characters.</param>
        /// <returns>bool</returns>
        public static bool ContainsAnyOf(this string password, string listofcharacters)
        {
            return password.ContainsAnyOf(listofcharacters.ToCharArray());
        }

        /// <summary>
        /// Checks if the string has a space.
        /// </summary>
        /// <param name="txt">Any string.</param>
        /// <returns>bool</returns>
        public static bool HasSpaces(string txt)
        {
            if (txt.Contains(" "))
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// To be a strong password, Must have 3 out of 4 of the following conditions:
        /// Uppercase, lowercase, numberic, symbol
        /// </summary>
        /// </summary>
        /// <param name="password"></param>
        /// <returns></returns>
        public static bool IsPasswordStrong(this string password)
        {
            int numTypes = 0;

            if (HasUppercaseCharacter(password) == true)
            {
                numTypes = numTypes + 1;
            }
            if (HasLowercaseCharacter(password) == true)
            {
                numTypes = numTypes + 1;
            }
            if (HasNonAlphaNumeric(password) == true)
            {
                numTypes = numTypes + 1;
            }
            if (HasDigit(password) == true)
            {
                numTypes = numTypes + 1;
            }

            if (numTypes > 2)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public static bool HasUppercaseCharacter(string str)
        {
            if (str == str.ToLower())
                return false;
            return true;
        }

        public static bool HasLowercaseCharacter(string str)
        {
            if (str == str.ToUpper())
                return false;
            return true;
        }

        public static bool HasDigit(string str)
        {
            Regex regexNums = new Regex("[0-9]");
            return regexNums.IsMatch(str);
        }

        public static bool HasNonAlphaNumeric(string str)
        {
            string newString = str;

            Regex regexNums = new Regex("[0-9]");
            Regex regexAlphas = new Regex("[a-z]", RegexOptions.IgnoreCase);

            newString = regexNums.Replace(newString, "");
            newString = regexAlphas.Replace(newString, "");

            return (newString.Length > 0);
        }

        /// <summary>
        /// This adds a function to a string object that RC4 Encrypts a password.
        /// </summary>
        /// <param name="password">A password as a string.</param>
        /// <returns>A byte[] representation of an RC4 password.</returns>
        public static byte[] Encrypt(this string password)
        {
            try
            {
                // Encode the password
                System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
                byte[] encryptedPwd = encoding.GetBytes(password);

                // encrypt password
                Encrypt(encryptedPwd.Length, encryptedPwd);
                return encryptedPwd;
            }
            catch (Exception ex)  
            {
                throw ex;
            }
        }

        /// <summary>
        /// This adds a function to a byte[] object that decrypts an RC4 password.
        /// and returns the password as a string.
        /// </summary>
        /// <param name="encryptedPwd">A byte[] representation of an RC4 password.</param>
        /// <returns>The password as a string.</returns>
        static public string Decrypt(this byte[] encryptedPwd)
        {
            string password = string.Empty;
            try
            {                
                    // decrypt password
                    Decrypt(encryptedPwd.Length, encryptedPwd);

                    // convert from byte array to string
                    password = System.Text.ASCIIEncoding.Default.GetString(encryptedPwd);
                    password = password.Replace("\0", string.Empty);                
            }
            catch (Exception ex) 
            {
                throw ex;
            }
            return password;
        }

        public static string FirstLetterUpperCase(this string inString)
        {
            if (string.IsNullOrEmpty(inString))
                return string.Empty;

            string newString = inString.Substring(0, 1).ToUpper();
            newString += inString.Substring(1, inString.Length - 1);
            return newString;
        }

        public static string LimitTo(this string data, int length) 
        {
            return data.Length < length ? data : data.Substring(0, length);
        }
    }
}

How to have the TextBlock in a left column of a Grid in a ListView Template expand or shrink with text wrapping?

Ok, lets say you want to have a Grid where each item is a row of data in a Grid. The left most column should expand or shrink, and yes the text should wrap when it shrinks.

Not so easy…but it can be done if you use the right tools.

  • Use a DockPanel not a Grid
  • Make the left most column the last one added
<Window x:Class="ListBoxWithWrap.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        d:DesignHeight="242"
        d:DesignWidth="388"
        >
    <Grid>
        <DockPanel Name="MainGrid" HorizontalAlignment="Stretch">
            <!-- These four blocks will have other content eventually, but only need to be 45 wide -->
            <TextBlock Text="X" Grid.Column="1" HorizontalAlignment="Center" Width="45" DockPanel.Dock="Right"/>
            <TextBlock Text="X" Grid.Column="2" HorizontalAlignment="Center" Width="45" DockPanel.Dock="Right"/>
            <TextBlock Text="X" Grid.Column="3" HorizontalAlignment="Center" Width="45" DockPanel.Dock="Right"/>
            <TextBlock Text="X" Grid.Column="4" HorizontalAlignment="Center" Width="45" DockPanel.Dock="Right"/>
            <!-- This is the TextBlock that needs to wrap its content (and
                             change the height of the row (so the full content is still
                             visible) to whatever the available space is, but should not
                             make overall ListView wider than the parent's width. -->
            <TextBlock Text="A very long string that should wrap when the window is small." Padding="20,6,6,6" TextWrapping="Wrap" DockPanel.Dock="Right"/>
        </DockPanel>
    </Grid>
</Window>

You will see that this works as you desire.

Now put this in a ListView’s Template and set it to use Binding.

<Window x:Class="ListBoxWithWrap.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        mc:Ignorable="d"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        d:DesignHeight="242"
        d:DesignWidth="388"
        SizeToContent="WidthAndHeight">
    <Grid>
        <ListView Name="lvWrap" ItemsSource="{Binding}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <DockPanel Name="MainGrid" HorizontalAlignment="Stretch">
                        <!-- These four blocks will have other content eventually, but only need to be 45 wide -->
                        <TextBlock Text="X" Grid.Column="1" HorizontalAlignment="Center" Width="45" DockPanel.Dock="Right"/>
                        <TextBlock Text="X" Grid.Column="2" HorizontalAlignment="Center" Width="45" DockPanel.Dock="Right"/>
                        <TextBlock Text="X" Grid.Column="3" HorizontalAlignment="Center" Width="45" DockPanel.Dock="Right"/>
                        <TextBlock Text="X" Grid.Column="4" HorizontalAlignment="Center" Width="45" DockPanel.Dock="Right"/>
                        <!-- This is the TextBlock that needs to wrap its content (and
                             change the height of the row (so the full content is still
                             visible) to whatever the available space is, but should not
                             make overall ListView wider than the parent's width. -->
                        <TextBlock Text="{Binding Content}" Padding="20,6,6,6" TextWrapping="Wrap" DockPanel.Dock="Right"/>
                    </DockPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Window>

Now give it some data to bind to.

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

namespace ListBoxWithWrap
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            List<SomeItem> list = new List<SomeItem>();
            list.Add(new SomeItem() { Content = "Some very long string with so many words there should be some wrapping going on to prevent a line of text that is too long" });
            list.Add(new SomeItem() { Content = "Some very long string with so many words there should be some wrapping going on to prevent a line of text that is too long" });
            list.Add(new SomeItem() { Content = "Some very long string with so many words there should be some wrapping going on to prevent a line of text that is too long" });
            list.Add(new SomeItem() { Content = "Some very long string with so many words there should be some wrapping going on to prevent a line of text that is too long" });
            list.Add(new SomeItem() { Content = "Some very long string with so many words there should be some wrapping going on to prevent a line of text that is too long" });

            lvWrap.DataContext = list;
        }

        public class SomeItem
        {
            public string Content { get; set; }
        }
    }
}

The shrink with text wrapping no longer works once inside of the ListView. So that tells you that something to do with the ListView is breaking the feature you want.

Here is how you fix this:

1. Open your project in Expression Blend. (If you don’t have Expression Blend, maybe just look at my code below and copy it)

2. Right-Click on the ListView in the Object and Timeline tab and choose Edit Template | Edit a Copy.

3. Click OK on the next Window.

This will create the following resource code.

<Window.Resources>
		<SolidColorBrush x:Key="ListBorder" Color="#828790"/>
		<Style x:Key="ListViewStyle1" TargetType="{x:Type ListView}">
			<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
			<Setter Property="BorderBrush" Value="{StaticResource ListBorder}"/>
			<Setter Property="BorderThickness" Value="1"/>
			<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
			<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
			<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
			<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
			<Setter Property="ScrollViewer.PanningMode" Value="Both"/>
			<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
			<Setter Property="VerticalContentAlignment" Value="Center"/>
			<Setter Property="Template">
				<Setter.Value>
					<ControlTemplate TargetType="{x:Type ListView}">
						<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="1" SnapsToDevicePixels="true">
							<ScrollViewer Focusable="false" Padding="{TemplateBinding Padding}">
								<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
							</ScrollViewer>
						</Border>
						<ControlTemplate.Triggers>
							<Trigger Property="IsEnabled" Value="false">
								<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
							</Trigger>
							<Trigger Property="IsGrouping" Value="true">
								<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
							</Trigger>
						</ControlTemplate.Triggers>
					</ControlTemplate>
				</Setter.Value>
			</Setter>
		</Style>
	</Window.Resources>

4. Now look at what is surrounding the ItemPresenter. Yes, you see the ScrollViewer, which is your problem. Delete it.

5. Build you project.

Success! Now your feature to both expand or shrink with text wrapping is back.

Here is the final XAML.

<Window x:Class="ListBoxWithWrap.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        mc:Ignorable="d"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        d:DesignHeight="242"
        d:DesignWidth="388"
        SizeToContent="WidthAndHeight">
    <Window.Resources>
        <SolidColorBrush x:Key="ListBorder" Color="#828790"/>
        <Style x:Key="ListViewStyle1" TargetType="{x:Type ListView}">
            <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
            <Setter Property="BorderBrush" Value="{StaticResource ListBorder}"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
            <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
            <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
            <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
            <Setter Property="ScrollViewer.PanningMode" Value="Both"/>
            <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListView}">
                        <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="1" SnapsToDevicePixels="true">
                            <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                            </Trigger>
                            <Trigger Property="IsGrouping" Value="true">
                                <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <ListView Name="lvWrap" ItemsSource="{Binding}" Style="{DynamicResource ListViewStyle1}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <DockPanel Name="MainGrid" HorizontalAlignment="Stretch">
                        <!-- These four blocks will have other content eventually, but only need to be 45 wide -->
                        <TextBlock Text="X" Grid.Column="1" HorizontalAlignment="Center" Width="45" DockPanel.Dock="Right"/>
                        <TextBlock Text="X" Grid.Column="2" HorizontalAlignment="Center" Width="45" DockPanel.Dock="Right"/>
                        <TextBlock Text="X" Grid.Column="3" HorizontalAlignment="Center" Width="45" DockPanel.Dock="Right"/>
                        <TextBlock Text="X" Grid.Column="4" HorizontalAlignment="Center" Width="45" DockPanel.Dock="Right"/>
                        <!-- This is the TextBlock that needs to wrap its content (and
                             change the height of the row (so the full content is still
                             visible) to whatever the available space is, but should not
                             make overall ListView wider than the parent's width. -->
                        <TextBlock Text="{Binding Content}" Padding="20,6,6,6" TextWrapping="Wrap" DockPanel.Dock="Right"/>
                    </DockPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Window>

You should now have a little bit more understanding of the ListView template and how to manipulate it, which should translate to other objects in WPF as well.

How to copy a directory recursively in C#?

Today I had the task of copying a directory recursively in C#. The first thing I did was type into my project “Directory.” and see if intellisense brought up a function called Directory.Copy. Unfortunately there is not a Directory.Copy, which to me seems like an oversight, as copying a directory is fairly common. Maybe it is not an action commonly done in C#.

So next I went to my browser and did a search. Well, I am not the first, nor will I be the last to solve this. There are a number of solutions online and each seem to have both positive and negative comments.

Option 1 – A directory copy using recursion

Pros: This is simple and to the point and elegant.

Cons: One complaint is that this could cause a stack overly by using recursion but this might not be a valid con as the filesystem restrictions in Windows might prevent a stack overflow anyway.

Since I am dealing with a small controlled tree, the con will not affect me., but since we are dealing with a file system, this is likely not to occur.

        private static void CopyFilesRecursively(DirectoryInfo source, DirectoryInfo target)
        {
            foreach (DirectoryInfo dir in source.GetDirectories())
                CopyFilesRecursively(dir, target.CreateSubdirectory(dir.Name));
            foreach (FileInfo file in source.GetFiles())
                file.CopyTo(Path.Combine(target.FullName, file.Name));
        }

Option 2 – Use SearchOption.AllDirectories to create the directory structure then then copy all the files

Pros: Does not use recursion
Cons: Are there any?

        private static void CopyFilesRecursively(String SourcePath, String DestinationPath)
        {
            // First create all of the directories
            foreach (string dirPath in Directory.GetDirectories(SourcePath, "*", SearchOption.AllDirectories))
                Directory.CreateDirectory(dirPath.Replace(SourcePath, DestinationPath));

            // Copy all the files
            foreach (string newPath in Directory.GetFiles(SourcePath, "*.*", SearchOption.AllDirectories))
                File.Copy(newPath, newPath.Replace(SourcePath, DestinationPath));
        }

Option 3 – Use one of the methods recommended by MSDN

Unfortunately MSDN is not consistent, and recommends two different methods in two different places, which I am sure were written by different teams.

using System;
using System.IO;

class DirectoryCopyExample
{
    static void Main()
    {
        DirectoryCopy(".", @".\temp", true);
    }

    private static void DirectoryCopy(
        string sourceDirName, string destDirName, bool copySubDirs)
    {
      DirectoryInfo dir = new DirectoryInfo(sourceDirName);
      DirectoryInfo[] dirs = dir.GetDirectories();

      // If the source directory does not exist, throw an exception.
        if (!dir.Exists)
        {
            throw new DirectoryNotFoundException(
                "Source directory does not exist or could not be found: "
                + sourceDirName);
        }

        // If the destination directory does not exist, create it.
        if (!Directory.Exists(destDirName))
        {
            Directory.CreateDirectory(destDirName);
        }

        // Get the file contents of the directory to copy.
        FileInfo[] files = dir.GetFiles();

        foreach (FileInfo file in files)
        {
            // Create the path to the new copy of the file.
            string temppath = Path.Combine(destDirName, file.Name);

            // Copy the file.
            file.CopyTo(temppath, false);
        }

        // If copySubDirs is true, copy the subdirectories.
        if (copySubDirs)
        {

            foreach (DirectoryInfo subdir in dirs)
            {
                // Create the subdirectory.
                string temppath = Path.Combine(destDirName, subdir.Name);

                // Copy the subdirectories.
                DirectoryCopy(subdir.FullName, temppath, copySubDirs);
            }
        }
    }
}

Or the different one they posted here:

using System;
using System.IO;

class CopyDir
{
    public static void CopyAll(DirectoryInfo source, DirectoryInfo target)
    {
        if (source.FullName.ToLower() == target.FullName.ToLower())
        {
            return;
        }

        // Check if the target directory exists, if not, create it.
        if (Directory.Exists(target.FullName) == false)
        {
            Directory.CreateDirectory(target.FullName);
        }

        // Copy each file into it's new directory.
        foreach (FileInfo fi in source.GetFiles())
        {
            Console.WriteLine(@"Copying {0}\{1}", target.FullName, fi.Name);
            fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true);
        }

        // Copy each subdirectory using recursion.
        foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
        {
            DirectoryInfo nextTargetSubDir =
                target.CreateSubdirectory(diSourceSubDir.Name);
            CopyAll(diSourceSubDir, nextTargetSubDir);
        }
    }

    public static void Main()
    {
        string sourceDirectory = @"c:\sourceDirectory";
        string targetDirectory = @"c:\targetDirectory";

        DirectoryInfo diSource = new DirectoryInfo(sourceDirectory);
        DirectoryInfo diTarget = new DirectoryInfo(targetDirectory);

        CopyAll(diSource, diTarget);
    }

    // Output will vary based on the contents of the source directory.
}

Option 4 – Use Microsoft.VisualBasic

Pros: One line.
Cons: You have to reference an additional dll that you otherwise do not need.
This additional dll is not available in Mono for cross-platform development.

new Microsoft.VisualBasic.Devices.Computer().
    FileSystem.CopyDirectory( sourceFolder, outputFolder );

There are various other methods:

Resources:
http://stackoverflow.com/questions/58744/best-way-to-copy-the-entire-contents-of-a-directory-in-c
http://msdn.microsoft.com/en-us/library/system.io.directoryinfo.aspx
http://msdn.microsoft.com/en-us/library/bb762914.aspx
http://xneuron.wordpress.com/2007/04/12/copy-directory-and-its-content-to-another-directory-in-c/
http://www.logiclabz.com/c/copy-directory-in-net-c-including-sub-folders.aspx

A quick overview of MVVM

Model View ViewModel (MVVM) is a design pattern based on Model View Controller (MVC) but specifically tailored to Windows Presentation Foundation (WPF).

MVVM is not a framework per se but many frameworks have been created. Here is a list of MVVM Frameworks from Wikipedia.

See the Wikipedia site here: Open Source MVVM Frameworks.

Another blog, has some basic information on many of these here: A quick tour of existing MVVM frameworks

A framework is actually not necessary to implement MVVM and you should seriously consider whether using one is right for your WPF application or not. Many applications do not need much of the features the frameworks provide. However, there are two common classes that all MVVM frameworks contain. These are ViewModelBase and RelayCommand. Though some frameworks may give them different names or implement them slightly differently, they all have these classes. For example, MVVM Foundation names the ViewModelBase differently. It is called ObservableObject, which is more appropriate because it is incorrect to assume that all objects that implement INotifyPropertyChanged are going to be ViewModel objects.

Instead of installing and using an MVVM framework, you could simply include these classes in your application, as these are all you need to implement MVVM.

  • ObservableObject
  • RelayCommand

While these two classes are enough, you may want to investigate how different MVVM Frameworks implement and what else they implement and why. You may find that another feature implemented is exactly what you need in your application and knowing about it could save you time.

The Array class in C#

System.Array is an important class to know and understand as almost any programming work has arrays.

Array is an abstract class, so you cannot establish and instance of it. That is OK because it is really just a “function holder” class.  The term “function holder” is not an official C# term, but it is a name I give classes that really just exist to hold functions.  Array is a “function holder” for array functions.

Lets take a moment to learn a few of the functions in the Array class. We are going to use an array of high scores to learn from.

Array.Sort

Let start by creating an array of high scores. The following code has a function that takes a score and adds it to the list if it is greater than the lowest high score and sorting them.

using System;

namespace ArrayLearning
{
    class Program
    {
        static int[] highScores = new int[12];

        static void Main(string[] args)
        {
            // keep that top 12 high scores
            AddScore(10100);
            AddScore(13710);
            AddScore(14190);
            AddScore(12130);
            AddScore(12130);
            AddScore(16140);
            AddScore(19320);
            AddScore(07250);
            AddScore(18140);
            AddScore(08090);
            AddScore(10010);
            AddScore(14380);
            AddScore(18140);
            AddScore(12190);
            AddScore(19320);
        }

        static void AddScore(int newScore)
        {
            // Pre-sort the high scores in case somehow the
            // first one is not the lowest.
            Array.Sort(highScores);

            // If the new score is greater than the lowest
            // high score, replace the lowest high score
            if (highScores[0] < newScore)
                highScores[0] = newScore;

            // Now resort the scores as the new score may
            // not be in the right place
            Array.Sort(highScores);

            DisplayHighScores();
        }

        private static void DisplayHighScores()
        {
            // Print the new high scores
            for (int i = highScores.Length - 1; i > -1; i--)
            {
                Console.WriteLine(highScores[i]);
            }
            Console.WriteLine("Press any key to continue");
            Console.ReadKey();
            Console.WriteLine();
        }
    }
}

Ok, I am not saying this is the proper way to handle high scores in a game.  I am just demonstrating Array.Sort for you.

Array.Clear

Ok, lets show an example of Array.Clear. This is a very simple function that sets all the values in the array to their default value. Booleans have a default value of false. Double, Int32, Int64, etc, have a default value of 0. Reference types have a default value of null.

Here is an enhancement to the above snippet that allows demonstrates clearing an entire array. Notice Array.Clear takes the array, then the starting item in the array and the number items in the array. In this example we clear the entire array, but that is not required.

using System;

namespace ArrayLearning
{
    class Program
    {
        static int[] highScores = new int[12];

        static void Main(string[] args)
        {
            // keep that top 12 high scores
            AddScore(10100);
            AddScore(13710);
            AddScore(14190);
            AddScore(12130);
            AddScore(12130);
            AddScore(16140);
            AddScore(19320);
            AddScore(07250);
            AddScore(18140);
            AddScore(08090);
            AddScore(10010);
            AddScore(14380);
            AddScore(18140);
            AddScore(12190);
            AddScore(19320);

            // Clear the high scores
            ClearHighScores();
        }

        static void AddScore(int newScore)
        {
            // Pre-sort the high scores in case somehow the
            // first one is not the lowest.
            Array.Sort(highScores);

            // If the new score is greater than the lowest
            // high score, replace the lowest high score
            if (highScores[0] < newScore)
                highScores[0] = newScore;

            // Now resort the scores as the new score may
            // not be in the right place
            Array.Sort(highScores);

            DisplayHighScores();
        }

        public static void ClearHighScores()
        {
            Console.WriteLine("Clearing High Scores!");
            Array.Clear(highScores, 0, highScores.Length);
            DisplayHighScores();
        }

        private static void DisplayHighScores()
        {
            // Print the new high scores
            for (int i = highScores.Length - 1; i > -1; i--)
            {
                Console.WriteLine(highScores[i]);
            }
            Console.WriteLine("Press any key to continue");
            Console.ReadKey();
            Console.WriteLine();
        }
    }
}

Array.IndexOf

Maybe you want to display the place in the top 12 that the player scored. However, the way we are adding the score does not track the new score’s place. So we need to find the place. Here is a small enhancement to the above code that demonstrates the use of Array.IndexOf to find the place.

Notice the addition of the DisplayCurrentPlace function and it’s use of Array.IndexOf. Also since the array is actually sorted with the lowest number at index 0 and the highest score at index 11, I can just subtract the index from the max lengh of 12 high scores to get the correct place.

using System;

namespace ArrayLearning
{

    class Program
    {
        public static int MAX = 12;
        static int[] highScores = new int[MAX];

        static void Main(string[] args)
        {
            // keep that top 12 high scores
            AddScore(10100);
            AddScore(13710);
            AddScore(14190);
            AddScore(12130);
            AddScore(12130);
            AddScore(16140);
            AddScore(19320);
            AddScore(07250);
            AddScore(18140);
            AddScore(08090);
            AddScore(10010);
            AddScore(14380);
            AddScore(18140);
            AddScore(12190);
            AddScore(19320);
            AddScore(06320);

            // Clear the high scores
            ClearHighScores();
        }

        static void AddScore(int newScore)
        {
            // Pre-sort the high scores in case somehow the
            // first one is not the lowest.
            Array.Sort(highScores);

            // If the new score is greater than the lowest
            // high score, replace the lowest high score
            if (highScores[0] < newScore)
            {
                highScores[0] = newScore;

                // Now resort the scores as the new score may
                // not be in the right place
                Array.Sort(highScores);

                DisplayHighScores();
                DisplayCurrentPlace(newScore);
            }
        }

        public static void ClearHighScores()
        {
            Console.WriteLine("Clearing High Scores!");
            Array.Clear(highScores, 0, highScores.Length);
            DisplayHighScores();
        }

        private static void DisplayHighScores()
        {
            // Print the new high scores
            for (int i = highScores.Length - 1; i > -1; i--)
            {
                Console.WriteLine(highScores[i]);
            }
        }

        private static void DisplayCurrentPlace(int newScore)
        {
            Console.WriteLine(String.Format("You placed number {0} out the top 12.", MAX - Array.IndexOf(highScores, newScore)));

            Console.WriteLine("Press any key to continue");
            Console.ReadKey();
            Console.WriteLine();
        }
    }
}

Well, these were three simple examples of using the Array class. As you can see it is little more than a “function holder”.

If you have an example of a function in the Array class, please post it here in the comments.

Getting better with the String and StringBuilder classes in C#

So we all use the Strings in C# and most of us consider ourselves experts.  But are we really experts.  When you’re getting tested and you don’t have Visual Studio or MSDN in front of you, are you ready to answer the questions with confidence?

Sometimes it is worth while to re-learn the basics because often simple features you are not using would save you time and prevent you from failing to appear as knowledgeable as you really are. Especially if you have not had a project where you manipulate strings, because you do other complex tasks and you do little more with strings than assign them values and compare them.

Well, here are the two links to the String and StringBuilder objects on MSDN.

Take a moment and read the MSDN pages about these objects even if you have read them before.

Here are some questions that you should answer about these classes.

  1. Which is mutable and which is immutable? What does that mean?

    Answer:

    String is immutable.  That means that once you create a string, it cannot be altered in place in memory, but instead, any alteration causes a copy with the modification to be created in a new memory location and the reference is updated to refer to the copy. For example if you append a character you actually get a whole new string in a whole new memory location.

    StringBuilder is mutable.  That means that you can change the object in place in memory without creating a copy.  For example, if you append a character to StringBuilder it can add it to the same space in memory.  There is one exception.  If you add so many characters that the next character you add make the string bigger than the memory location’s capacity, a new object in memory is created. The default capacity for this implementation is 16 characters, and the default maximum capacity is Int32.MaxValue. (1) So if you are playing with Strings greater than 16 characters, you should instantiate your StringBuilder objects with a capacity greater than 16.

  2. So can you modify a string in place in memory?

    Answer:

    No. And yes.

    Read this MSDN article: How to: Modify String Contents (C# Programming Guide)

    The short version of the above article is that you can’t normally. But if you use “unsafe” you can, the above link provides the following unsafe code:

    class UnsafeString
    {
        unsafe static void Main(string[] args)
        {
            // Compiler will store (intern)
            // these strings in same location.
            string s1 = "Hello";
            string s2 = "Hello";
    
            // Change one string using unsafe code.
            fixed (char* p = s1)
            {
                p[0] = 'C';
            }
    
            //  Both strings have changed.
            Console.WriteLine(s1);
            Console.WriteLine(s2);
    
            // Keep console window open in debug mode.
            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }
    }
    

    Would you actually do this though?

  3. What is the easiest way to reverse a String?
        public static string ReverseString(string s)
        {
    	char[] arr = s.ToCharArray();
    	Array.Reverse(arr);
    	return new string(arr);
        }
    

    Notice another C# class called Array was used. This class, like String and StringBuilder, is another class that you may be forgetting about an overlooking.

    When I was asked how to reverse a string, the Array.Reverse function did not come to mind and so I recreated it with this function, which obviously takes more time and a developer’s time is too expensive to recreate work already done for you.

        private static String Reverse(String inString)
        {
            char[] myChars = inString.ToCharArray();
            for (int i = 0, j = inString.Length - 1; i < inString.Length / 2; i++, j--)
            {
                char tmp = inString[j];
                myChars[j] = inString[i];
                myChars[i] = tmp;
            }
            return new string(myChars);
        }
    
  4. Which is more efficient for concatenation or appending characters, String or StringBuilder?

    StringBuilder is by far more efficient. Microsoft has a knowledge base article on this here: http://support.microsoft.com/kb/306822

    I changed the code slightly to use the Stopwatch to time the ticks to get more accurate data.

    using System;
    using System.Diagnostics;
    
    namespace StringBuilderPerformance
    {
        class Program
        {
            static void Main(string[] args)
            {
                // The greater the loops the better the performance ratio
                const int sLen = 30, Loops = 10000;
                int i;
                string sSource = new String('X', sLen);
                string sDest = "";
                //
                // Time string concatenation.
                //
                Stopwatch timer = new Stopwatch();
                timer.Start();
                for (i = 0; i < Loops; i++) sDest += sSource;
                timer.Stop();
                long stringTicks = timer.ElapsedTicks;
                Console.WriteLine("Concatenation took " + stringTicks + " ticks.");
                //
                // Time StringBuilder.
                //
                timer.Reset();
                timer.Start();
                System.Text.StringBuilder sb = new System.Text.StringBuilder((int)(sLen * Loops * 1.1));
                for (i = 0; i < Loops; i++) sb.Append(sSource);
                sDest = sb.ToString();
                timer.Stop();
                long stringBuilderTicks = timer.ElapsedTicks;
                Console.WriteLine("String Builder took " + stringBuilderTicks + " ticks.");
                Console.WriteLine("Using StringBuilder takes " + ((double)stringBuilderTicks / (double)stringTicks * (double)100).ToString("F") + "% of the time that using String takes.");
    
                //
                // Make the console window stay open
                // so that you can see the results when running from the IDE.
                //
                Console.WriteLine();
                Console.Write("Press any key to finish ... ");
                Console.ReadKey();
            }
        }
    }
    

    Here are the results:

    Concatenation took 5338055 ticks.
    String Builder took 2213 ticks.
    Using StringBuilder takes 0.04% of the time that using String takes.

    Press any key to finish …

Anyway, I hope this post helps you remember the basics.

A WPF front-end for LDPing

I wrote a front-end to LDPing last week-end. You can check it out here:

LDPing

So I was writing a WPF front-end for LDPing, which is a method of querying a LANDesk Agent for its computer name and Inventory Id. There is a button that you click to launch the ping and I couldn’t get the thing to enable…Anyway, I figured it out and posted the resolution here:

Refreshing a button enabled/disabled by RelayCommand.CanExecute()

So here is a screen shot of LDPing.

How to disable row selection in a WPF DataGrid?

Disabling row selection in the WPF DataGrid included in .NET Framework 4 is not really easy. It is extremely difficult to do, unless you have the right tools and know exactly how to do it.

But all the difficulty is in figuring out how to do it. Once you know how to do it, the steps are quite easy to perform.

First, you basically have to use a copy of the default DataGrid style. However, the easiest way to get a copy of the default DataGrid style is using Expression Blend.

Read more one my new WPF Sharp site here:

How to disable row selection in a WPF DataGrid?

How to create a copy of a control’s default style?

Sometimes you need to make some advanced styling changes to a default control, such as a RadioButton, ListBox, DataGrid, Button, etc. However, you may want to keep the majority of the default style the way it is.

In Expression Blend, this is easy to do. If you don’t have Expression Blend and you are developing in WPF, get it immediately. There is a trial version you can test out.

Here is how to get your copy of any control’s default style….

Read more on my new WPF Sharp site
How to create a copy of a control’s default style?

See my article on Mono in the BSD Magazine May issue

The BSD Magazine has released and there is an article in it by yours truly.

Check it out.

May issue of BSD magazine- Embedded BSD: FreeBSD and Alix

C# – The ?? operator or coalesce operator

Here is a little code that returns either x or y. It returns y if x is null, otherwise it returns x.
return (x == null) ? y : x;

The coalesce operator is basically short hand for this. The ?? operator simplifies and shortens the above expression.
return x ?? y;

10 Step process for developing a new WPF application the right way using C#

It makes a difference if you do something the right way from the beginning.  Everything seems to work out so much better and takes less time over all.

Here are some basic steps that I have learned will help you do it right the first time. These steps are from my experience, mostly because I did it wrong the first few times.  These are not exact steps. They are subject to change and improve.  In fact, you might have improvements to suggest immediately when you read this. But if you are new to WPF, then reading these steps before you start and following them, will have you closer it doing it the right way the first time.  It is much more pleasant to tweak a pretty good process than it is to go in with no idea for a process and do it wrong.

Step 1 – Prepare the idea

  1. Some one has an idea
  2. Determine the minimal features for release 1.
  3. Determine the minimal features for release 2.
    1. Alter minimal features for release 1 if it makes sense to do so.
  4. Determine the minimal features for release 3.
    1. Alter minimal features for release 1 and 2 if it makes sense to do so.

Step 2 – Design the Application’s back end business logic (simultaneous to Step 3)

  1. Design the backend
  2. Apply the “Keep it simple” idea to the business logic and makes changes as necessary.
  3. Apply the “Keep it secure” idea to the business logic and makes changes as necessary.
  4. Repeats steps 2 and 3 if necessary.
  5. Backend development can start now as the UI and the back end should not need to know about each other, though this coding is listed as the Step 5 item.

Step 3 – Design the UI using WPF (simultaneous to Step 2)

  1. Determine what development model should be used to separate the UI from the business logic.
    1. Model-View-ViewModel (MVVM) is the model I recommend for WPF.
    2. Gather libraries used for the model (such as common MVVM libraries that include the common ViewModelBase and RelayCommand objects)
  2. Consider using a 3rd party WPF control set will be used.  Many 3rd party companies provide WPF controls that are better and easier to use than those included by default.
    1. If you decided to use 3rd party controls, purchase or otherwise obtain the libraries for these 3rd party controls.
  3. Consider designing two WPF interfaces or skins (I will call these Views from here on out) for each screen. This will help drive the separation of the back end code from the WPF code. Also if developing two Views is not simple, it indicates a poor design.
  4. Design the interface(s) (you may be doing two Views) using SketchFlow (take time to include the libraries for the 3rd party WPF Controls in your SketchFlow project and design with them)
    1. SketchFlow allows you to design the UI, which is commonly done in paint, but instead does this in XAML, and is actually the WPF code your application will use.
  5. SketchFlow allows you to deliver the design (or both Views if you did two) as a package to the customer.
    1. Deliver it immediately and get feedback.
    2. Make changes suggested by the customer if in scope.
  6. Take time to make the XAML in SketchFlow production ready.
  7. Deliver the XAML to the customer again, to buy of that the design changes are proper.
    1. Make changes suggested by the customer if in scope.

Step 4 – Determine the delivery or install method

  1. Determine the delivery method.
  2. Determine when to develop the delivery method.
    1. The easier the application is, the longer you can wait to determine the installer or delivery method.
    2. The more complex the install or delivery method, the sooner this should be started.

Step 5 – Develop the business logic

  1. Develop the application designed in step 2.
  2. Get the application working without UI or silently. Note: Start the next step, Develop the UI, as soon as enough code is available here.

Step 6 – Add Bindings to the UI

  1. Start the UI project by copying the XAML from the SketchFlow document to your Visual Studio or Expression Blend project.
  2. Determine a method for setting the DataContext without linking the View to any ViewModel or Model dlls.
  3. Create a project for the ViewModel code and develop it to interact with the business logic using Binding.
  4. Remember to develop two Views for every UI screen as this will help, though not guarantee, that the the MVVM model was correctly used.

Step 7 – Develop the View Model

  1. You should now have a backend code and a View, and now you start creating the View Model.
  2. This should be in a separate dll than the View or ViewModel.
  3. The ViewModel should never link to the View but can link to Model and Business libraries, though you may consider interface-based design and only link to an interface library.
  4. Make sure to use the properties that the View is binding to.

Step 8 – Consider a other platforms

Macintosh

Macintosh owns a significant market share.  Determine if this application needs to run on Macintosh as well. Sure, since we are running C# your options are limited to either rewriting in objective C and Coca, or using Mono with a MonoMac UI.  I recommend the latter.

Note: It is critical that the UI and business logic are separated to really make this successful.

  1. Completely ignore the WPF design and have Macintosh users users assist the design team in designing the new UI.  Macintosh’s have a different feel, and trying to convert the same UI is a mistake.
  2. Create the MonoMac UI project.
  3. Create a project similar to the ViewModel project in Windows, to link the UI to the business logic.

BSD/Linux/Unix

BLU (BSD/Linux/Unix) doesn’t exactly own a significant market share. However, it is still important to determine if this application needs to run on on BLU as well. Sure, since we are running C# your options are limited to either rewriting in C++, or using Mono with a GTK# or Forms UI.

  1. Completely ignore the WPF and Macintosh designs and have Linux users assist the design team in designing the new UI. Linux have a different feel, and trying to convert the same UI is a mistake.
  2. Create the GTK# project.
  3. Create a project similar to the ViewModel project in Windows, to link the UI to the business logic.
  4. GTK# doesn’t support binding, but still keep the UI separate from the business logic as much as possible.
  5. Also, don’t develop for a single open source flavor, but use standard code that compiles and any BSD/Linux/Unix platform.

Mobile Platforms

  1. Do you need to have this app on IOS or Android or Windows Phone?
  2. Completely ignore the WPF and Macintosh and Linux designs and have Android or IOS users assist the design team in designing the new UI. Mobile platforms have a different feel, and trying to convert the same UI is impossible as the screens are much smaller.

Step 9 – Develop the delivery method

Again, you may need to do this way sooner if the application is complex.

  1. Develop the install or delivery method.
  2. If you decided to deploy to Macintosh or BLU you may have to develop separate install or delivery methods for those platforms as well.
  3. Remember to have a plan and a test for your first patch even if you have to mock a sample patch before you release.
  4. Remember to have a plan and a test for upgrading your application even if you have to mock a sample upgrade version before you release.

Step 10 – Deliver the finished Products

  1. Once finished, deliver this product.
  2. If you decided to create a Macintosh or BLU version, deliver them when ready as well.  It is OK and maybe preferred to deliver these at different times.