Saturday, 22 December 2012

WPF Validation Adorners in Tab Control Disappear when Tabs Changed

I found recently than the Validation Error Adorners on my WPF Project when used within a Tab Control, would disappear if I changed tabs.

After a little searching, I found this helpful post;

http://karlshifflett.wordpress.com/2008/02/19/wpf-validation-errors-disappear-inside-tabcontrol-when-switching-tabitems/

You basically need to wrap your Tab Control Tab Content within a Adorner Decorator as follows;

<Border>      
    <AdornerDecorator>            
        <StackPanel>                  
            ...           
        </StackPanel>      
    </AdornerDecorator>
</Border>

This “bug” is due to the fact that the Error Adorners are painted on the Adorner Layer, which is discarded when changing tabs. The code above preserves this layer, preventing the Adorners from being lost.

Friday, 21 December 2012

Reactivate Windows Embedded 7 180 Day Trial

Recently the 180 Day trial of my development Windows 7 Embedded install expired. This necessitated that I attempt to reset the Grace Period.
The following seems to work;
  • Open Command Prompt under Elevated Privileges
  • Enter “slmgr.vbs /rearm” and press Enter
  • Wait for the command to complete, and ok the dialog box
  • Restart your system
  • Windows should prompt that it is not genuine
  • Open Command Prompt under Elevated Privileges again
  • Enter “slmgr.vbs –atp” and press Enter
  • Ok the Dialog Box
  • Restart Windows
  • Goto your System Properties
  • The machine should now have 180 days once more

Sunday, 16 December 2012

Obtaining the Maximum value in a list or Collection using Linq

In order to retrieve the highest value of a column in a list of collection, Linq offers a handy method to achieve this;

Dim maxUnitsInStock = Aggregate prod In db.Products _
                      Into Max(prod.UnitsInStock)

Simple!

Tuesday, 4 December 2012

Enabling MVVM INotifiyPropertyChanged in EF 5 POCO Entities created using the EF 5.x DbContext Generator

While combining EF5 with WPF MVVM, I noticed that changes to individual properties within my bound DataContext weren’t updating the UI.

This was of course because the the actual DataContext itself isn’t changing, but only the POCO Properties housed within in. However, each of the POCO Properties don’t individually raise an INotifyPropertyChanged event.

In order to implement this, one must modify the T4 Template provided as part of the EF 5.x DbContext Generator, to insert the extra lines which add the relevant code to Implement the Interface, and raise the INotifiyPropertyChanged Event.

This is performed by making the following modifications to the T4 Template;

(Note, I work in vb.net here, the code will be different for a c'# implementation!)

  1. Open you’re .tt file
  2. Find the Section which loops through all of the Complex Types in your model, which begins with the line “For Each loopComplex As ComplexType…”.
  3. Below the Line saying “Partial <#=Accessibility.ForType(complex)#> Class <#=code.Escape(complex)#>”, add the following two lines of code;

    Implements INotifyPropertyChanged
    Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged

    This Implements the INotifiyPropertyChanged Interface, and adds the Public Events to each of the POCO’s for your Complex Types.

  4. Find the Write Header Sub, which starts with “Public Sub WriteHeader(ByVal fileManager As EntityFrameworkTemplateFileManager)”
  5. Below the “<#” and the line saying “fileManager.StartHeader()”, add the following line of code;



    Imports System.ComponentModel

    This adds a reference to “System.ComponentModel” , which is where INotifiyPropertyChanged lives.
  6. Find the AnyProperty Function, which starts with “Public Function AnyProperty(accessibility As String, type As String….
  7. Replace the whole function with the following code;



    Public Function AnyProperty(accessibility As String, type As String, name As String, getterAccessibility As String, setterAccessibility As String, defaultValue As String)
            Return String.Format( _
                    CultureInfo.InvariantCulture, _
                    "{6}    Private _{0} As {1}{2}{6}" & _
                    "    {3} Property {0} As {1}{6}" & _
                    "        {4}Get{6}" & _
                    "            Return _{0}{6}" & _
                    "        End Get{6}" & _
                    "        {5}Set(ByVal value As {1}){6}" & _
                    "            _{0} = value{6}" & _
                    "            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(""{0}"")){6}" & _
                    "        End Set{6}" & _
                    "    End Property",  _
                    name, _
                    type, _
                    defaultValue, _
                    accessibility, _
                    getterAccessibility, _
                    setterAccessibility, _
                    Environment.NewLine)
        End Function

    This enforces that all Properties are created with their full Getter’s and Setter’s, and adds the code to raise the PropertyChanged Event<

  8. Find the “EntityClassOpening” Function, which starts with the Line “Public Function EntityClassOpening(entity As EntityType) As String
  9. Replace the entire Function with the following Code;



    Public Function EntityClassOpening(entity As EntityType) As String
            Return String.Format( _
                CultureInfo.InvariantCulture, _
                "Partial {0} {1}Class {2}{3}{4}{5}{4}{6}", _
                Accessibility.ForType(entity), _
                _code.SpaceAfter(_code.MustInheritOption(entity)), _
                _code.Escape(entity), _
                _code.StringBefore(Environment.NewLine & "         Inherits ", _typeMapper.GetTypeName(entity.BaseType)), _
                Environment.NewLine, _
                "Implements INotifyPropertyChanged", _
                "Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged")
        End Function

    This adds the Implementation and Public Event for the INotifyPropertyChanged Interface

  10. Save your template, you may need to open your Model and save this also. Finall build your project, and you should have some fully declared Properties along with the INotifiyPropertyChanged code!


I hope this helps!