Thomas's profileBlogsBlogLists Tools Help

Blog


    03 February

    WPF AttachedProperties

    An AttachedProperty is similar to a DependencyProperty, except that the owner of the value is not the UIElement itself but an external UIElement. For instance, the Canvas.Left and Canvas.Top are AttachedProperties.
     
     
    In Xaml, you usually assign an AttachedProperty the following way:

    <Button Canvas.Left="12" Canvas.Top="44">ButtonText<Button>

     
    Now if you want to create an own AttachedProperty, you simply use the propdp code snippet to create a DependencyProperty first:

    public int Order
    {
         get { return (int)GetValue(OrderProperty); }
        set { SetValue(OrderProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Order. This enables animation, styling, binding, etc...
    public static readonly DependencyProperty OrderProperty =
        DependencyProperty.Register("Order", typeof(int), typeof(MyContainer), new UIPropertyMetadata(0));

     
    To change the DependencyProperty to an AttachedProperty, simply replace DependencyProperty.Register to DependencyProperty.RegisterAttached.
     
    But if you try to attach this Property to a control, it doesn't work!
    You need to Add static Getters and Setters instead of the local "Offset properties in the following way:

    public static int GetOrder(UIElement e)
    {
        if (e == null) throw new ArgumentNullException("e");
        return (int)e.GetValue(OrderProperty);
    }

    public static void SetOrder(UIElement e, int value)
    {
        if (e == null) throw new ArgumentNullException("e");
        e.SetValue(OrderProperty, value);
    }
     
     
    And finally, you have created an AttachedProperty you can use with other Controls.
     
    Here is the complete code:

    [

    ContentProperty("Items")]
    public class MyContainer : ItemsControl
    {
        static MyContainer()
        {
            DefaultStyleKeyProperty.OverrideMetadata(
    typeof(MyContainer), new FrameworkPropertyMetadata(typeof(MyContainer)));
        }

        public static int GetOrder(UIElement e)
        {
            if (e == null) throw new ArgumentNullException("e");
           
    return (int)e.GetValue(OrderProperty);
        }

        public static void SetOrder(UIElement e, int value)
        {
            if (e == null) throw new ArgumentNullException("e");
            e.SetValue(OrderProperty, value);
        }

        // Using a DependencyProperty as the backing store for Order. This enables animation, styling, binding, etc...
       
    public static readonly DependencyProperty OrderProperty =
            DependencyProperty.RegisterAttached("Order", typeof(int), typeof(MyContainer), new FrameworkPropertyMetadata((int)0));
        }

     

    Now you can use it the following way:

    <

    Window x:Class="AttachedProp.Window1"
        xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
        xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
        xmlns:m="clr-namespace:AttachedProp"
       
    Title="Window1" Height="300" Width="300">
       
    <Grid>
            <m:MyContainer>
                <Button Canvas.Bottom="3" m:MyContainer.Order="3">OK</Button>
           
    </m:MyContainer>
        </Grid>
    </
    Window>

     

    Now if you want to use the AttachedProperty within  a ControlTemplate you cannot simply use TemplateBinding. The following snippet shows the correct syntax.

     

    <Style TargetType="{x:Type local:MyControl}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:MyControl}">
                    <Border Background="{TemplateBinding Background}" Height="40"
                                 BorderBrush="{TemplateBinding BorderBrush}"
                                 BorderThickness="{TemplateBinding BorderThickness}">
                          <TextBlock Text="{Binding Path=(local:MyContainer.Order), RelativeSource={RelativeSource TemplatedParent}}" />
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    Notice the surrounding bracket on the Path property which is mandantary as well as the appearance of Path. Thus you cannot use the following shortcut:

    <

    TextBlock Text="{Binding local:MyContainer.Order RelativeSource={RelativeSource TemplatedParent}}" Background="Red" MinHeight="24" />

    02 December

    Symmetric Encryption with windows mobile

     
    The .NET Framework offers a lot of different symmetric and asymetric encryption algorithm, as well as the compact framework for window mobile. But one important class is missing in the compact framework:

    Rfc2898DeriveBytes

    This class provides functionality to create key data from an arbitary password string, which is required for every encryption algorithm. You cannot simply convert the password string to a byte[] array using e.g. Encoding.Default.ToArray(password), since the key must  be of a specific size. The size can vary by different blocks and it depends on the algorithm you are using. For instance, the prefered AES or Rijndael algorithm requires a key size of 128, 256, 384, etc. but nothing between. Therefore you need an algorithm that encodes any string to a byte array of at least 128 bytes and not less or more.

    Fortunately, this is what hashing algorithm's do! So as a replacement for the missing Rfc2898DeriveBytes, we can use a has algorithm, that belongs to the compact framework, and that creates a size that matches the requirements for the encryption algorithm. In this case, since we are  using AES, we need a hash with a size of 128 or 256, and the qualified match is the MD5 algorithm. It is not the strongest though, and SH256 would be the better choice, but unfortunately, the compact framework does not include this hash algorithm, so we need to use MD5.

     Here comes an example of how to implement encryption/decryption for windows mobile:

    /// <summary>
    /// Encrypts a string using symmetric encryption.
    /// </summary>
    /// <param name="message">The message string to be encrypted.</param>
    /// <param name="password">The password for encryption.</param>
    /// <returns>A byte array with the encrypted message.</returns>
    public byte[] EncryptSymmetric(string message, string password)
    {
       // RijndaelManages is the prefered symmetric algorithm, since it has the strongest encryption and it is completely managed code:
       SymmetricAlgorithm sa = new RijndaelManaged();
      
       // apply key and IV to the algorithm, depending on password:
       PasswordToKey(password, sa);
      
       byte
    [] binary = Encoding.Unicode.GetBytes(message);
       MemoryStream ms = new MemoryStream();
       CryptoStream stream = new CryptoStream(ms, sa.CreateEncryptor(), CryptoStreamMode.Write);
       stream.Write(binary, 0, binary.Length);
       stream.FlushFinalBlock();
       stream.Close();
       byte[] encrypted = ms.ToArray();
      
       return
    encrypted;
    }

    /// <summary>
    /// Decrypts a byte array to a string, using symmetric encryption.
    /// </summary>
    /// <param name="encrypted">The encrypted data as byte array.</param>
    /// <param name="password">The password for decryption.</param>
    /// <returns>A string with the decrypted message.</returns>
    public string DecryptSymmetric(byte[] encrypted, string password)
    {
       // RijndaelManages is the prefered symmetric algorithm, since it has the strongest encryption and it is completely managed code:
       SymmetricAlgorithm sa = new RijndaelManaged();

       // apply key and IV to the algorithm, depending on password:
       PasswordToKey(password, sa);
       using (MemoryStream ms = new MemoryStream())
       {
          using (CryptoStream stream = new CryptoStream(ms, sa.CreateDecryptor(), CryptoStreamMode.Write))
          {
             stream.Write(encrypted, 0, encrypted.Length);
             stream.Flush();
             stream.Close();
          }
          byte[] decrypted = ms.ToArray();
          string s = Encoding.Unicode.GetString(decrypted);
          return s;
       }
    }


    /// <summary>
    /// Generates key and IV from the specified password, using an MD5 hash.
    /// </summary>
    /// <remarks>
    /// Usually you would prefer to use Rfc2898DeriveBytes for this purpose but since
    /// .net compact framework (for windows mobile) does not have any implementation
    /// for Rcf2898DeriveBytes or even PasswordDeriveBytes, this is a simple workaround
    /// for it.
    /// </remarks>
    /// <param name="password">The password to generate a key/ITfrom it.</param>
    /// <param name="sa">The SymmetricAlgorithm class for which to create a key/IV pair.</param>
    private static void PasswordToKey(string password, SymmetricAlgorithm sa)
    {
       HashAlgorithm hashAlgo = new MD5CryptoServiceProvider();
       byte[] hash = hashAlgo.ComputeHash(Encoding.UTF8.GetBytes(password));
       sa.BlockSize = hash.Length * 8;
       sa.Key = hash;
       sa.IV = hash;
    }


    private void button1_Click(object sender, EventArgs e)
    {
       string message = "This is the message to be encrypted";
       string password = p@ssw0rD;

       byte
    [] encrypted = EncryptSymmetric(message, password);
       string decrypted = DecryptSymmetric(encrypted, password);

       MessageBox.Show(decrypted);
    }
     

     

     

    19 November

    How to make a Microsoft Certificate

    Almost one year ago, I decided to make all the necessary certificates to become a MCPD, a Microsoft Certified Professional Developer. This title sound like a very big honor, and indeed it is. Passing a Microsoft Certificate is not as easy as I assumed, and this is my story:

     

    For .NET 2.0, Microsoft offers multiple grades of certificates. You need to pass 2 exams to become either a web, windows or distributed application MCTS (Microsoft certified technology specialist). All of them have the 70-536 exam in common, which in my opinion is the most difficult of them. In addition, for each of these 3 certificates you can upgrade to become a MCPD by passing one additional exam which differs for each category with one exception: for the 70-549 exam that grades you the rank of a Microsoft certified professional Developr for Enterprise Applications, you need to pass all previous MCTS certificates and this is what I'm longing for.

    There are different ways to pass these exams. You can join a 2 week training course, which is about $5000, or you can simply buy the required books and make a self paced training. The books include a training software from measureup to test your knowledge. But you'd better don't rely on the knowledge you'll receive by making all 300 tests again and again and again until you memorize them. Because the real exam tests are completely different! You really need to know the issues that are included in the exam category to pass them.

    It took me 3 weeks to read and prepare for the 70-536 exam, the "Application Development Foundation" which I mentioned earlier. I was also grabbing for some reports of other graduates who made this exam to figure out how exactly it works and how difficult it is. When I'd read that the real exam is supposed to be much harder than then the measureup test, I was frightened! Because the measureup test are anything else but easy! Even if you have years of .net experience like me or other developers, the questions are a pain in the ass. But on the other hand, I heard and read that the real tests are easier, they'd be obvious, and so, last week I decided to make my first exam as soon as possible and applied for a test this Monday.

    This works as followed:

     

    There are many test centers, where you can make a Microsoft exam or other exams. For a Microsoft exam (note: not a complete certificate that consists of multiple exams!) you have to pay €140 for the exam itself and additionally a fee for the test center which is about €20-30. To find a test center near your location, you first need to register at www.prometric.com then you can follow the links to the exam of your choice and select a test center at your location. Sometimes, there are more than one centers for the same city available. Next step, you choose the day of your choice when you want to make the exam (If a test center doesn't offer the date, maybe you can select another one). Finally, you select the time when you want to make the exam,which depends on the selected center. I could choose within 9:00 and 17:00. The duration of a test is scheduled to take 3:15 hours. You also can choose of the either English, French, German, Japanese or Chinese for the exam. (I chose English as my Japanese needs a little improvement).

    After you have selected you're appointment, you'll receive an e-mail confirmation.

     

    I chose Monday because it gives me a complete weekend to prepare for it. Against all odds, I was neither tensed nor I was nervous and on Sunday, I slept very well. I still was relaxed when I arrived at the test center:

    So there I was, to match me intellect, to become one of the most important people of the universe.
    After filing in at the reception, I had to authenticate myself with an certified document including a pass photo (usually your identity card). You can't take any book, computer, notebook, pda or cell phone to the test. If you keep one of these with you, you'll need to hand out them. Next step, guarding you to a prepared room with computers and surveillance where you'll gonna spend the next 3 hours (or maybe less) of your life. Three hours, that will change your life forever!

    I still wasn't tensed or nervous when I was introduced to my computer, handing out an empty peace of paper and a pen for notes that I could make (but I was not in the mood of making any kind of notes or drawings or anything like that). Before the exam starts, you'll click trough some informations about the test and the conditions. For instance, it's not allowed to make any photos or copies of the text, or to spread them on the internet or stuff like this. You got 60 minutes or so for that, and when you feel ready, when you're of the opinion that you will make it, that the sake of the whole universe is in your hand, then you can press the final button and the exam begins. Now you have 120 minutes for 45 questions. You need to get a score of 700 of 1000, so you need to pass only 70%. But the catch is, that each question is weighted differently, so it doesn't mean that you need to have 31.5 correct questions.

     

    After seeing the first question, I was totally calm. The question was not that difficult, so I experienced the next 4 questions. Now I was tensed! And I was nerveous! I was wondering where that steady knocking came from and I figured out that it was my heard beating! These questions have been totally knew to me and in no test that I made for preps earlier, I've seen anything similar like this! I was wondering If I do understand the question. What does it mean, what do they want from me? Why can't they leave me alone? until question 31, I was alone in the room when another candidate was introduced to that room on another computer. I heared every click he made with the mouse and it was sooo distracting. I couldn't concentrate, I was counting the pauses between a click and was wondering why he was clicking so fast! Propably another test, as my test was a lot of stuff to read and to scroll down to find a difference between answer a,b,c or d.  Anyway, I could not concentrate on the test as long as he keeps klicking all the time like a maniac!

    Finally, after question 45, the last one, I had almost one hour left so I checked each question again. 10 minutes left I thought that I couldn't do more for me and the whole mankind. So I clicked the "finish" button. I was a little bit scared as the screen became white for a couple of minutes. What If all my answers are lost? What I this means I would not pass my exam?

    But then there as a screen again. But it was not the result of my test! No, I now have the chance to leave comments for each question. I wanted to make some comments to some of the question where it seamed clear to select the correct answer, but I didn't find them spontaneously and I was too curious if I will have passed the exam, so I clicked finished again.

     

    And finally, there it was, the answer of all questions, The salavation of the lost. The truth!

    And the answer was "Congratulation, you passed your exam".

    I was hand out a document, with the detailed result for all 7 categories of my test (but not the each question) and then I was free to go. To continue my journey on the way to become a respected MCPD.

     

     

    20 April

    Partial classes

    Partial classes is a nice feature coming with .NET 2.0. With partial classes, it is possible to split one bigger class into separate files. For instance, Visual Studio 2005 automatically separates the business and design logic of a control class into to files: filename.cs and filename.designer.cs.

    For some purposes it could be very neat to separate parts of a class that belong to a group of functionality into some more files. To do this, you simply need to create a new file, name it ClassName.addition.cs. Visual Studio 2005 treats all file names before the first point as one, so you only need to define in both files the class with the partial keyword e.g.:

     

    public partial class MyClass

    {

    }

     

    As I mentioned, it really makes sense, for instance, I got a form that has an edit and a display mode, so I separated the business logic of these modes into separate files, so I don't lose track of it.