Tuesday, January 06, 2009

I am taking the Quickstarts Commanding as an example.

1. Build Commanding.sln

a. silverlightut binaries

Symptom - you may get heaps of compilation errors. Here is one example:

…\CAL\Silverlight\Composite.Presentation.Tests\App.xaml.cs(19,17): error CS0234: The type or namespace name 'Silverlight' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)

Cause – The referenced Microsoft.Silverlight.Testing.dll & Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight.dll are missing

Solution – Download the “Silverlightut” (Silverlight Unit test framework) from http://code.msdn.microsoft.com/silverlightut | Extract the two dlls to LIB\Silverlight\UnitTestFramework | Restart VS IDE 

b. ValidateXaml

Symptom – You may get the following error:

Cause – No clue except the VS installation is possibly messed up somewhere.

Solution – Upload the project file | Modify ValidateXaml node from true to false | Save changes & Reload the project

2. Build Commanding.Tests.AcceptanceTest.sln

a. white binaries

Symptom – you may get heaps of compilation errors. Here is an example:

…\AcceptanceTestLibrary\AcceptanceTestLibrary\ApplicationHelper\WhiteExtensions.cs(21,7): error CS0246: The type or namespace name 'Core' could not be found (are you missing a using directive or an assembly reference?)

Cause – The referenced Core.dll & Bricks.dll are missing

Solution – Download the “White Binaries” from http://www.codeplex.com/white  | Extract to LIB\White

b. project hint path

Symptom – you may still get heaps of compilation errors similar to 2a

Cause – The Commanding.Tests.AcceptanceTest.csproj has incorrect hint path for Core.dll & Bricks.dll

Solution – Unload the project file | Mofiy the HintPath from \LIB\Core.dll to \LIB\White\Core.dll | Modify the HintPath from \LIB\Bricks.dll to \LIB\White\Bricks.dll | Reload the project file | Restart the VS IDE

3. Test Commanding.Tests.AcceptanceTest

a. Test run error

Symptom – You may get the Test Run Errors and Warnings

Failed to queue test run '…': Test Run deployment issue: The location of the file or directory '...\quickstarts\commanding\commanding.tests.acceptancetest\commanding.tests.acceptancetest\bin\debug\Core.dll' is not trusted

Cause – As the error message correctly indicates, we need to trust the referenced White assemblies.

Solution – Open \LIB\White\Core.dll properties | Unblock & Apply/OK | Rebuild Commanding.Tests.AcceptanceTest.sln

Note – Make sure you are unblocking the assemblies in the LIB not the bin\debug.

b. Test run failed

Symptom – You may get the error message:

System.IO.FileNotFoundException: Could not load file or assembly 'Castle.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc' or one of its dependencies

Cause – The depending White assemblies are missing

Solution – Make sure the following assemblies are under \LIB\White

  • Bricks.RuntimeFramework
  • Castle.Core
  • Castle.DynamicProxy2
  • log4net
  • nunit.framework
  • White.NUnit
  • Xstream.Core

Note – If you click the “Test run failed” link, the “Test Run Errors and Warnings” actually listed all the missing assemblies.

Note2 – Make sure you unblock the above assemblies as well.

Wednesday, December 31, 2008

I ran into a problem that the Command CanExecute is not invoked when the CommandSource's CommandParameter is updated.

For example, this spike application (download source code here) displays a window with a title and two buttons.

CommandManagerNotDetermineCommandParameterChange Window

this.CommandBindings.Add(new CommandBinding(Commands.OldTitle, OldTitleExecuted, OldTitleCanExecute));

this.CommandBindings.Add(new CommandBinding(Commands.NewTitle, NewTitleExecuted, NewTitleCanExecute));

The "OldTitle" button should only be enabled if the window's title is "Window New".

void OldTitleCanExecute(object sender, CanExecuteRoutedEventArgs e)

{

string title = e.Parameter as string;

e.CanExecute = !string.IsNullOrEmpty(title) && 0 == string.Compare(title, Constants.TtileNew);

}

The "OldTitle" will change the window's title to "Window Old".

void OldTitleExecuted(object sender, ExecutedRoutedEventArgs e)

{

ChangeTitleAsync(Constants.TitleOld);

}

The "NewTitle" button should only be enabled if the window's titile is "Window Old".

The "NewTitle" will change the window's title to "Window New".

Each of this buttons has its CommandProperty set to a static RoutedUICommand and its CommandParameterProperty set to the window's title.

<Button

Command="{x:Static sun:Commands.OldTitle}"

CommandParameter="{Binding ElementName=window, Path=Title}"

Content="{Binding Source={x:Static sun:Commands.OldTitle}, Path=Text}" />

<Button

Command="{x:Static sun:Commands.NewTitle}"

CommandParameter="{Binding ElementName=window, Path=Title}"

Content="{Binding Source={x:Static sun:Commands.NewTitle}, Path=Text}" />

The RoutedUICommand's Execute code will fire up a background worker to sleep a short while, then return the new title (or old) to be set to the Windows's title.

private void ChangeTitleAsync(string title)

{

BackgroundWorker bw = new BackgroundWorker();

bw.DoWork += new DoWorkEventHandler(ChangeTitle);

bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(ChangeTitleCompleted);

bw.RunWorkerAsync(title);

}

void ChangeTitleCompleted(object sender, RunWorkerCompletedEventArgs e)

{

BackgroundWorker bw = sender as BackgroundWorker;

if (bw != null)

{

bw.Dispose();

bw = null;

}

string title = e.Result as string;

if (!string.IsNullOrEmpty(title))

{

this.Title = title;

}

//CommandManager.InvalidateRequerySuggested();

}

void ChangeTitle(object sender, DoWorkEventArgs e)

{

System.Threading.Thread.Sleep(1000);

e.Result = e.Argument;

}

Since the windows' title is a dependency property, and it is referenced in the CommandParameter via DataBinding, so as soon as the window's title is set, the CommandParameter is updated. (You can prove this by throwing in a TracingConverter in the DataBinding).

However, the update of CommandParameter does not cause the Command's CanExecute being re-evaluted.

One solution is to force a CommandManager to raise the RequerySuggested event via the InvalidateRequerySuggested static method. And in the examle above, one place to call it reactively is in the end of the background worker completed handler since we just touched the window's Title.

void ChangeTitleCompleted(object sender, RunWorkerCompletedEventArgs e)

{

...

CommandManager.InvalidateRequerySuggested();

}

In summary, as MSDN has pointed out:

In situations where the CommandManager does not sufficiently determine a change in conditions that cause a command to not be able to execute, InvalidateRequerySuggested can be called to force the CommandManager to raise the RequerySuggested event.

 

Friday, October 03, 2008

I passed 70 502 MS WPF Exam today, scored 873. It is not a very pretty score comparing to my 1000 for 70 536, but pass is a pass

Even though it took almost 2 hours to complete all questions and review a dozen marked ones, I think it is a reasonably easy exam.

I reckon the sectional results (evaluating the strength of each area) is quite spot on, it shows exactly those weak area of my knowledge.

In terms of my preparation, apart from doing WPF at work for the last six months, I did spend some spare time studying the MSDN. But that is it, I did not use any WPF books.

Sunday, April 06, 2008

I went to Mrs Macquarie's Point today, and checked out the 1st Reb Bull FLUGTAG Sydney. It was so much fun.
It was all about rather stupidity than intelligence. :) It didn't give me wiiings, but it brought me plenty laugh.
There were almost 30000 people turned up to the event. For a city like Sydney, with not so big population, this is a very good marketing campaign by Red Bulls. As I can remember, the last time I saw this many people was when the Queen Mary 2 & QE2 met in Sydney harbor in 2007.

Saturday, April 05, 2008

If a Visual Studio solution contains a project that uses LINQ to SQL classes (.dbml), the Windows installer project will fail to build.

Here is an example.
The following illustrates the solution, project, and file structure.
 Solution1.sln
  |- ClassLibrary1.csproj
      |- DataClasses.dbml
  |- Setup1.vdproj
      |- Primary output from ClassLibrary1

When building this solution, I always get the following message:
========== Build: 1 succeeded or up-to-date, 1 failed, 0 skipped ==========

If I check the setup project output path, the setup.msi is generated there. And running the installer successfully deploys the classlibrary1.dll.

Here comes the surprising work around.
open the ClassLibrary1.csproj in the editor (Unload Project | Edit ClassLibrary1.csproj)
remove (or comment out) the following node
  <ItemGroup>
    <Service Include="{3259AA49-8AA1-44D3-9025-A0B520596A8C}" />
  </ItemGroup>
reload project
restart the IDE
build solution
========== Build: 2 succeeded or up-to-date, 0 failed, 0 skipped ==========

So what is this ItemGroup/Service/@Include="{3259AA49-8AA1-44D3-9025-A0B520596A8C}"?
Googling this GUID did not come up any useful info
However, the Windows registry editor helped to locate this under HKLM/SOFTWARE/Microsoft/VisualStudio/9.0/Services. It looks related to the O/R data class designer. This is very strange that it affects Visual Studio when building the setup (.vdproj).

Anyway, after removing (or commenting out) the node from the class library project (.csproj), I can build the whole solution again. And I have not seen any impact either on working with the LINQ to SQL data classes.