Posts
28
Comments
28
Trackbacks
0
Sunday, December 14, 2008
St. Louis Day of .NET

Yesterday was the St. Louis Day of .NET event (hencefore I'll refer to STLDODN); it was a great success!.

I was fortunate enough to be involved in this grand event; Clint Edmonson asked if I would be available to present some Microsoft PDC material, and I took that opportunity - even got to choose which topic to present.  I chose to do a presentation on Parallel Programming for Managed Code Developers.  Thanks for the chance, Clint.

To make sure I'm well prepared, I also volunteered to present it at Kansas City Day of .NET last week.  I blogged about it and also provided my presentation materials/samples in that post.  I did not change my presentation materials, so slides & samples (both for VS2010 CTP and Parallel Extensions June CTP versions) are available in this post.  These materials will also be made available at the STLDODN website later on (after the people have some rest ). 

In any case, it was an awesome day; some 200+ attendees came, presentations split into 6 tracks / rooms - got to meet some of my peers & friends there as well.  This event would not have happened without the heroic efforts of the 3 main organizers: Jeff Fattic, Kevin Grossnicklaus and Scott Spradlin - kudos and my hats off to them in organizing all this into fruition.  Quite a bit of sponsors donated to this cause; and fun was had for everyone.

For those that may have attended my presentation, can I get some feedback on the presentation?  I'm not sure what's the best way to do this yet; I guess commenting on this post (or the KC post) would be fine for the moment.  I'm always on the lookout as to what improvements that I can make to my presentation (slides / samples / materials) & my presentation skills so I can continue to be a better presenter.  I'm very new at this, and I am trying to make sure I learn as much as possible within the shortest amount of time - it's a long road to become a good presenter, so I need to run as fast as I can.

I got to attend other sessions that are presented; I thought the Developing Multi-Touch Applications session by Brian Blanchard was awesome.  He brought in an HP SmartTouch PC, which is a PC + Touch Screen combined, but the touch screen can recognize 2 touch areas (imagine like it can handle 2 mouse / 2 click events), and showed some cool stuff on utilizing the 2 touch areas to manipulate stuff - it's no Microsoft Surface, but to see something in action in front of me was great!

Eric Brown provided Open Source Solutions to Application Lifecyle Management, back-to-back with a session about VSTS 2010, attendees could contrast the two approaches - it was interesting indeed.  Chris Deweese did a session about Oslo, and man Microsoft didn't make it easy on him; the tools and packages he had to work with was very, very early in development - he did his best though and focuses on how some development challenges can be solved using a Model-Driven development.

At the end of yesterday, I was beat; unbelievably beat.  I think I was also very nervous the day before the event, thus earning me only 3 hours of sleep going into the event.  I slept like 14 hours before I woke up today; can't say that I'm fully refreshed yet, but I felt soooo much better at the moment .  Regardless, cheers to everyone I got to see at the event, and let this first STLDODN become a sign of bigger things to come.

posted @ Sunday, December 14, 2008 3:47 PM | Feedback (6)
Monday, December 08, 2008
Parallel Programming presentation materials

Kansas City hosted a Kansas City Day of .NET this past Saturday; I was fortunate enough to be given the opportunity by Lee Brandt to present there.  Wonderful time was had for all, food & drinks were provided along with some nice raffled items at the end.  Kudos to the 3 facilitators of this event: Lee Brandt, Becky Isserman and Doug Butscher.

In any case, I was there presenting Parallel Programming for Managed Code Developers; essentially re-delivering Daniel Moth's excellent PDC presentation.

For those that may be interested, the PowerPoint to that presentation is here, and the source code zip file is here (PFX June CTP version) or here (VS2010 CTP version).  The difference between the 2 sources is that the June CTP has a different method for the Task/Future creation (Create vs. StartNew), otherwise everything else is the same.

To run the executable, you need to either have the PFX June CTP installed, or run it in the VS2010 CTP Virtual Machine - please make sure you get the proper version for your environment.  Please note that at the moment the only way to have the VS2010 CTP on the guest VM to recognize more than 1 processor is to run it under Windows Server 2008 Hyper-V.

In my presentation, I walked through changing the code from single-threaded, to multi-thread, to multi-task, to using Future, to LINQ and eventually to demonstrate Parallel LINQ.  All the different codes are available in the Logic.cs file; that class has several ProcessColorsXXX method; the XXX defines the code methodology used (thread, task, etc.).

I hope this is beneficial to others.

posted @ Monday, December 08, 2008 2:14 PM | Feedback (0)
Monday, November 17, 2008
Displaying Rich-Formatted Text in WPF

One project was put forth that essentially requires creating a MessageBox look-alike, but the text supports rich-format, and we can do it in WPF.  It's a pretty neat task, and in this post I'll focus on just the text side; the easiest way possible most probably is to just use a RichTextBox control, make it to have no border, and everything will be fine.  However, I'd like to do it efficiently as well.

FormattedText can be used; however it's hard to make it generic - essentially code has to be written to show the text in the desired font/color.  The TextBlock class supports using some flow content elements, and it is described as very lightweight; so let's use that.  The sample provided shows the fact that it can display rich-formatted text:

XAML for the Textblock (from MSDN sample):

What the Textblock looks like (from MSDN sample):

This is fine when what you want to display resides in its own XAML; how about making it generic, where the consumer can specify the text to display, and also control the format/color/font size of the text - preferably also making the string to be available from resources?  Looking around, RichTextBox has a sample on how to get its content and the decorations.  Using the same methodology it works, but the returned string looks rather convoluted:

 

Code: 

private string GetTextBlockXAMLContent(TextBlock textBlock)
{
   // Get the content being displayed
   TextRange range = new TextRange(textBlock.ContentStart, textBlock.ContentEnd);
 
   // Save the content to stream and get it back as byte array
   MemoryStream stream = new MemoryStream();
   range.Save(stream, DataFormats.Xaml);
   byte[] bytes = stream.ToArray();
 
   // Convert to character and rebuild it into a string
   StringBuilder stringBuilder = new StringBuilder(bytes.Length);
   List<char> chars = new List<char>(bytes.Select(b => Convert.ToChar(b)));
   chars.ForEach(ch => stringBuilder.Append(ch));
 
   return stringBuilder.ToString();

}

Resulting string:
<Section xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xml:space="preserve" TextAlignment="Left" LineHeight="Auto" IsHyphenationEnabled="False" xml:lang="en-us" FlowDirection="LeftToRight" NumberSubstitution.CultureSource="User" NumberSubstitution.Substitution="AsCulture" FontFamily="Tahoma" FontStyle="Normal" FontWeight="Normal" FontStretch="Normal" FontSize="11" Foreground="#FF000000" Typography.StandardLigatures="True" Typography.ContextualLigatures="True" Typography.DiscretionaryLigatures="False" Typography.HistoricalLigatures="False" Typography.AnnotationAlternates="0" Typography.ContextualAlternates="True" Typography.HistoricalForms="False" Typography.Kerning="True" Typography.CapitalSpacing="False" Typography.CaseSensitiveForms="False" Typography.StylisticSet1="False" Typography.StylisticSet2="False" Typography.StylisticSet3="False" Typography.StylisticSet4="False" Typography.StylisticSet5="False" Typography.StylisticSet6="False" Typography.StylisticSet7="False" Typography.StylisticSet8="False" Typography.StylisticSet9="False" Typography.StylisticSet10="False" Typography.StylisticSet11="False" Typography.StylisticSet12="False" Typography.StylisticSet13="False" Typography.StylisticSet14="False" Typography.StylisticSet15="False" Typography.StylisticSet16="False" Typography.StylisticSet17="False" Typography.StylisticSet18="False" Typography.StylisticSet19="False" Typography.StylisticSet20="False" Typography.Fraction="Normal" Typography.SlashedZero="False" Typography.MathematicalGreek="False" Typography.EastAsianExpertForms="False" Typography.Variants="Normal" Typography.Capitals="Normal" Typography.NumeralStyle="Normal" Typography.NumeralAlignment="Normal" Typography.EastAsianWidths="Normal" Typography.EastAsianLanguage="Normal" Typography.StandardSwashes="0" Typography.ContextualSwashes="0" Typography.StylisticAlternates="0" HasTrailingParagraphBreakOnPaste="False">
 
 <Span NumberSubstitution.CultureSource="Text" FontWeight="Bold">
 <Run>TextBlock</Run>
 </Span>
 <Run NumberSubstitution.CultureSource="Text">is designed to be</Run>
 <Span NumberSubstitution.CultureSource="Text" FontStyle="Italic">
 <Run>lightweight</Run>
 </Span>
 <Run NumberSubstitution.CultureSource="Text">, and is geared specifically at integrating</Run>
 <Span NumberSubstitution.CultureSource="Text" FontStyle="Italic">
 <Run>small</Run>
 </Span>
 <Run NumberSubstitution.CultureSource="Text">portions of flow content into a UI.</Run>
 </Section>

Essentially all the properties are set out; it makes things very hard to read - this can be a problem when we want to store the string in the resource, since translators only need to translate the literal parts.  The text size grows as well, causing quite a bit of size addition.  Is there a better shorthand?  I found one by using the XamlWriter / XamlReader constructs.

 

private object GetTextBlockXAMLContent(TextBlock textBlock)
{
   // Get the content being displayed
   string xaml = XamlWriter.Save(textBlock.Inlines);
   object o = XamlReader.Parse(xaml);
 
   return o;
}

However, when executing the code above, the XamlReader.Parse method throws a XamlParseException: Cannot create object of type 'System.Windows.Documents.InlineCollection'. CreateInstance failed, which can be caused by not having a public default constructor for 'System.Windows.Documents.InlineCollection'.  Error at Line 1 Position 2.  Apparently InlineCollection doesn't have a public default constructor.  Incidentally, the XamlReader.Parse method is new to .NET 3.5 SP1 (it is also added to .NET 3.0 SP2).  So we have to change the code so it enumerates through all the inlines as follows:

 

Code:

private string GetTextBlockXAMLContent(TextBlock textBlock)
{
   // Get the first inline
   Inline content = textBlock.Inlines.FirstInline;
 
   // If there are more than 1, then create a Span that
   // contains everything else
   if (textBlock.Inlines.Count > 1)
   {
      content = new Span();
      ((Span)content).Inlines.AddRange(textBlock.Inlines);
   }
 
   // Get the XAML that represents the TextBlock content
   string xaml = content == null ? null : XamlWriter.Save(content);
   return xaml;
}

XAML of the content:

<Span xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
 <Bold>TextBlock</Bold>
 is designed to be
 <Italic>lightweight</Italic>
 , and is geared specifically at integrating
 <Italic>small</Italic>
 portions of flow content into a UI.
 </Span>

Code to set TextBlock Content:

private void SetTextBlockXAMLContent(TextBlock textBlock, string xaml)
{
   // Clear textblock content
   textBlock.Inlines.Clear();
   if (xaml == null)
      return;
 
   // Add xaml content
   textBlock.Inlines.Add(XamlReader.Parse(xaml) as Inline);
}

As you can see, the XAML content is fairly compact, makes it easier to translate & store. Based on the example above since the TextBlock has more than 1 element in it, we're just encapsulating it inside a Span element, and that element is the one that is then serialized as XAML.  The last piece is code to restore the XAML content to a TextBlock.  Some things to note: the method is fairly slow, if you make a sample to get a content of a TextBlock and assign that content to another TextBlock, the first time it runs you can see that the operation is not instantaneous.  TextBlock also accepts only Inlines; and won't be able to fully display a complex FlowDocument.  I hope this can be of some use to others.

posted @ Monday, November 17, 2008 5:18 PM | Feedback (0)
Wednesday, September 17, 2008
Get return value from stored procedure

Recently we changed our DAC layer from using inline SQL to stored procedures in the database. On some of these SQL, we did record deletion (usually only 1 record), and we just execute it via IDBCommand.ExecuteNonQuery() and then check the return value to see how many records were affected (which should be 1) for verification that the query actually does something.

With the change to stored procedure, we just return 1 in the stored procedure if the delete is successful. However, the calling code then started to show these deletions as errors. Apparently ExecuteNonQuery only returns the number of affected rows on SELECT, INSERT and DELETE statements; for everything else it returns -1.  So I tried to figure out how to get a return value from a stored procedure.

Let's assume a simplistic stored procedure as follows:

ALTER PROC ReturnOnly
AS
BEGIN
      RETURN 5
END

You can't use ExecuteScalar to get the returned value, and ExecuteNonQuery will always return -1.  To get the value back, you need to add a return value parameter to the command.  The name of the parameter is not important.  The code to get the value returned by that procedure will be as follows:

private int ExecuteStoredProcedure(string storedProcedureName)
{
   SqlConnection connection = new SqlConnection(connectionString);
 
   // Command - specify as StoredProcedure
   SqlCommand command = new SqlCommand(storedProcedureName, connection);
   command.CommandType = CommandType.StoredProcedure;
 
   // Return value as parameter
   SqlParameter returnValue = new SqlParameter("returnVal", SqlDbType.Int);
   returnValue.Direction = ParameterDirection.ReturnValue;
   command.Parameters.Add(returnValue);
 
    // Execute the stored procedure
   connection.Open();
   command.ExecuteNonQuery();
   connection.Close();
 
   return Convert.ToInt32(returnValue.Value);
}

 

posted @ Wednesday, September 17, 2008 11:57 AM | Feedback (1)
Tuesday, August 26, 2008
Returning Cursor from Stored Procedure Executing Dynamic Query
I usually stay on the C# development of things, and rarely venture to create SQL statements/code, other than the occasional SELECT / UPDATE / INSERT.  However, we have a requirement from our Product Management group to DELETE records permanently from the database.  We have proper enforced foreign keys in our DB schema, so one option we have is to create a stored procedure to help deletion, which will walk thru the referencing foreign keys to the record being deleted and then also delete those records (the children records essentially).  Yes, I know records should not be deleted (it should just be marked as deleted or inactive or something), but it was a requirements insistence where my opinion was overridden.

Having the stored procedure (hence I'll refer to this as sproc) is nice since consumer just need to call the same sproc passing in the table name & record id to delete, and the sproc will do the heavy lifting.  However, the sproc has some tasks to solve; since children records can contain further children records, the sproc needs to call itself recursively.  Since the sproc needs to query different tables (depending on which record is deleted), the sproc has to build dynamic SQL statements and execute that.  Since you need the values of the record Ids that references the parent (so it can see if those records have further children), you also need a CURSOR to loop thru those Ids).

Separately, each of the problem is fairly simple enough, sprocs can call itself recursively, you can create sprocs that execute dynamic SQL, and you can have sprocs that has a CURSOR as OUTPUT.  However when you combine them together, I consider them to be a fairly neat challenge to try to tackle.  The hard part is actually with getting a CURSOR back from a dynamic SQL, so I'm going to focus on that part.

To execute dynamic SQL, you need to use the built-in sp_executesql sproc in SQL Server.  The sp_executesql sproc can accept the following parameters:
  1. The SQL statement that will be executed
  2. The parameters & types that's needed by the SQL statement (#1) in text format
  3. The actual parameters to use in that SQL statement

So, essentially sp_executesql will create a stored procedure, containing the SQL statement passed (#1), with the parameter list of that sproc as defined in #2 and then it will invoke that newly created stored procedure, passing in the parameters as defined in the latter parameters.

To solve the problem, then we just need to create a dynamic SQL that has a CURSOR parameter which is an OUTPUT parameter.  The following test sproc demonstrates this:

ALTER PROC TestProc

AS

       DECLARE @dynamicSQL nvarchar(200)

       -- Have code that will construct the dynamic SQL

       SET @dynamicSQL = 'SELECT FirstName FROM Contacts'

 

       -- The cursor that will be filled by the dynamic SQL

       DECLARE @outputCursor CURSOR

       -- Create the dynamic SQL to fill a CURSOR instead

       SET @dynamicSQL = 'SET @outputCursor = CURSOR FORWARD_ONLY STATIC FOR ' +

              @dynamicSQL + ' ; OPEN @outputCursor'

 

       -- Execute dynamic sql

       exec sp_executesql                  -- sp_executesql will essentially create a sproc

              @dynamicSQL,                 -- The SQL statement to execute (body of sproc)

              N'@outputCursor CURSOR OUTPUT', -- The parameter list for the sproc: OUTPUT CURSOR

              @outputCursor OUTPUT         -- The parameter to pass to the sproc: the CURSOR

 

       -- Code that will just output the values from the cursor

       DECLARE @firstName nvarchar(200)

       FETCH NEXT FROM @outputCursor INTO @firstName

 

       -- Loop while there're more things in the cursor

       WHILE @@FETCH_STATUS = 0

       BEGIN

              PRINT @firstName

              FETCH NEXT FROM @outputCursor INTO @firstName

       END

 

       -- Be nice, close & deallocate cursor

       CLOSE @outputCursor

       DEALLOCATE @outputCursor

I just choose to use a simple SELECT to a table as the dynamic SQL statement; you can make it to be whatever SELECT is needed based on parameter being passed.  Then the sproc declares a CURSOR, which will then be used to contain the result of the SQL statement.  The whole text, including the CURSOR is the dynamic SQL we want to execute.  sp_executesql is then called with the SQL statement, we then define the statement to have 1 parameter (which is the CURSOR as an OUTPUT parameter), and then we pass in the cursor as the object to pass into the dynamic SQL to be executed.  The latter half of the code just loops thru the cursor to proof that the results are proper.

Not having dealt with much SQL code, this was an interesting journey for me.  There are other ways to solve the problem (DELETE records), we can use cascade delete, but it doesn't support self-referencing tables.  In the end we didn't use this approach, instead we just create a sproc for each table that needs to be deleted; it seems like a heck of a lot of maintenance job, but I'll let the DBA handle that.
posted @ Tuesday, August 26, 2008 11:49 AM | Feedback (3)
Monday, August 25, 2008
Refresh / Update WPF controls
Sometime in the past, a friend asked me how to update a control to show status while his code is doing a loop of stuff.  Essentially changing the text of a label (or sophisticatedly we can say a text-based progress bar).  In my past coding with MFC and WinForms, it's fairly easy enough, you just invalidate and do an update (Invalidate / UpdateWindow in MFC or Invalidate / Update in WinForms).  This approach also coincides with how Windows UI operate, where you specify the region that needs to be redrawn and then you send a message to the message pump for that control to paint itself.

So, I expected something similar (if not exactly the same) to also be present in WPF; much to my surprise, there is no equivalent.   All my internet searches actually shows how to do this using background thread - it is the approach that needs to be taken in a proper programming context, however there are times when you just want to do something quick & dirty or you want to augment an existing app / port where you don't want to introduce new elements.  There are also considerations to be made when both UI and worker thread access the same data, especially with regard to data binding (see my post about collection change not supporting multi-threading out of the box).

So, I've decided to add a helper method to refresh a WPF control.  I really appreciated the Refresh method in WinForms (which executes both Invalidate & Update), so I'm renaming my method to be Refresh as well.  The code snippet below also show some C# specific techniques, namely: anonymous delegates and extension methods.

public static class ExtensionMethods

{

   private static Action EmptyDelegate = delegate() { };

 

   public static void Refresh(this UIElement uiElement)

   {
      uiElement.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
   }
}

private void LoopingMethod()

{
   for (int i = 0; i < 10; i++)
   {
      label1.Content = i.ToString();
      label1.Refresh();
      Thread.Sleep(500);
   }
}

The LoopingMethod is just the method I use in my Window class to update the label (updating the progress) and then the code does some heavy lifting (Sleep ).  The Refresh method is the extension method that takes any UI element and then calls that UIElement's Dispatcher's Invoke method.  The trick is to call the Invoke method with DispatcherPriority of Render or lower.  Since we don't want to do anything, I created an empty delegate.  So how come this achieves refresh functionality?

When the DispatcherPriority is set to Render (or lower), the code will then execute all operations that are of that priority or higher.  In the example, the code already sets label1.Content to something else, which will result in a render operation.  So by calling Dispatcher.Invoke, the code essentially asks the system to execute all operations that are Render or higher priority, thus the control will then render itself (drawing the new content).  Afterwards, it will then execute the provided delegate (which is our empty method).

Pretty weird; there was a post somewhere in my google search that led me this route, and I was surprised as to how it worked.  I couldn't find it anymore, but credit where credit is due, someone else figured out that Invoke-ing a Render or lower priority task will result in the UI being redrawn.
posted @ Monday, August 25, 2008 10:22 AM | Feedback (2)
Friday, August 22, 2008
Calling Generic Method when given a type
Every now and then I have a need to call a generic method, but I can't quite call it generically.  Usually that particular situation involves needing to call a generic method, and I have the type for that generic method.  There are various reasons/examples of why anyone would get to this point, in my case we have an infrastructure code that can deal with objects generically, but  because it is infrastructure code, we can't have it refer to the actual entity classes that are in the higher layer/tier.

However, if we only have the type, we can't just call the method as is, we have to call it via reflection.  And as much as I like reflection, it has some drawbacks.  Consider the following snippet:

public void InvokeGenericMethod(object o)

{

   MethodInfo mi = this.GetType().GetMethod("MyGenericTestMethod", BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Instance);

   mi = mi.MakeGenericMethod(new Type[] { o.GetType() });

   mi.Invoke(this, new object[] { o });

}
 

private string MyGenericTestMethod<T>(T value)

{

   return value.GetType().ToString();

}

To call the method (it is private), I have to call Type.GetMethod with some not very nice looking parameters.  The name supplied is in quotes; as such if the actual method name is changed, this code will still compile, it'll just crash when actually ran.  Mind you, the code works; it's just not very maintenance-friendly.

A trick I use for this then is to use delegates as follows:

public void InvokeGenericMethod(object o)

{

   Func<string, string> temp = MyGenericTestMethod<string>;

   MethodInfo mi = temp.Method.GetGenericMethodDefinition();

   mi = mi.MakeGenericMethod(new Type[] { o.GetType() });

   mi.Invoke(this, new object[] { o });

}
 

private string MyGenericTestMethod<T>(T value)

{

   return value.GetType().ToString();

}

By using delegates, I no longer need to use reflections to get the method to call; I just point to the method as a delegate, and then create a generic method definition from that delegate.  Everything after that is still the same.  One nice benefit to this is if the method name is changed, the refactoring engine will also change the delegate reference, and if it doesn't the code will fail at compile-time.  Nicer, cleaner looking code as well, IMHO.
posted @ Friday, August 22, 2008 9:41 AM | Feedback (0)
Wednesday, April 30, 2008
Pack URI Authority - Local Assembly = Executable

I had a post about accessing XAML resources using Pack URI, and actually had the chance to try it out.  The format of the pack URI is "pack://authority/path", and there are only 2 valid authority: application:/// and siteoforigin:///, as described in Microsoft's Pack URI documentation.

The path will just point to the resource you want to get; you can include the folder / subfolder, other assemblies (containing the resource), even versions of the assembly.  The simplest example they had was:

pack://application:,,,/ResourceFile.xaml

that points to ResourceFile.xaml in the local assembly.  What the documentation forget to define however, is what is local assembly; the local assembly is essentially the WPF executable.  If you have other XAML in a different assembly, and you have code in that same assembly to load the XAML using Pack URI, you have to treat it as if you're loading from a different assembly.

As an example, if you have a WPFResource.DLL which has a XAML resource (in this case test.xaml) you'd like to load, the code to load it will be as follows:

private static void InitializeWPFApplicationResources()
{
   Uri uri = new Uri("pack://application:,,,/WPFResource;component/test.xaml");
   Application.Current.Resources.Source = uri;
}

 The Pack URI has to refer to an external assembly - even though test.xaml resides in the same assembly with the executing code.  Anytime the pack URI doesn't refer to a different assembly, it will try to load the XAML resource from the executable file - I'm actually surprised with this, since it forces the Uri to always contain the assembly name which can be erroneous (say the assembly gets renamed).  Granted you can get around this problem by getting the assembly's name in code.

posted @ Wednesday, April 30, 2008 11:02 AM | Feedback (0)
Monday, April 28, 2008
Files downloaded by IE are marked Untrusted (or why the CHM file I downloaded didn't work)

I downloaded a CHM (Windows help) file for SharpZipLib software package to be used in my test app (pretty cool - allows me to do most stuff relating to zip files), and when I open the help file, none of the information shows.

Of course when I tried to open it up, Windows always asks me to verify that I wanted to open the file, with the dialog below:

However, even if I do allow this, the CHM file doesn't show its contents; the IE control that should display the help contents only show that the Program cannot display the webpage.  It turns out that this is a side effect of an IE security update - downloaded files are marked as untrusted and thus will require user's verification before it can be opened.  However, even if you verify for opening the files, the file itself is still marked untrusted, and as such IE will not allow rendering the information on the screen.

To fix this, you'd have to mark the uncheck the 'Always ask before opening this file' checkbox, and you're good to go.  You can also go to the file's properties and click the Unblock button near the bottom.  This situation puzzles me for a few minutes before the light bulbs start switching on.  I'm pretty sure I will get this again in the future and be puzzled the same way .

posted @ Monday, April 28, 2008 4:53 PM | Feedback (0)
Refer to resources in WPF with Pack URI

It's been over 2 months since I last updated my blog.  I have been busy; we got a new VP of IT and he made some changes and there are a bunch of stuff that's getting rejigged and people moved, projects retargeted, etc. etc.  In the end, it's not enough reason for me to not blog at all.

I started this blog so I can record my experiences with learning new stuff.  I have to say that I came back to this blog more than enough times to relook at the stuff I had learnt, to the point where my lapse in adding new stuff actually prevents me from being very productive - I learned some stuff that I should've put in here but I didn't, and in the end have to relearn it again since I didn't record it. D'uh.

Anyway, I need to be more disciplined and will try to be more active.  Relearnt something today about how to access file resources in WPF, instead of using the typical StaticResource or DynamicResource - use Pack URIs, as further detailed here.  The 2 important ones for me to remember are referencing items in the same assembly and in a different assembly (use the following format with the Source attribute in xaml):

pack://application:,,,/ResourceFile.xaml

pack://application:,,,/ReferencedAssembly;component/ResourceFile.xaml

This is actually very relevant to me; sometime last week, we had decided on trying to consolidate all our resources into a single DLL for each team project we have - it helps with internationalization (minimizing the number of DLLs), easier checking for entries that may already exist, can be used by other applications / modules if necessary, and can be swapped with another resource DLL or a newer one.

With our application, we won't actually use the pack URI to point to different XAML (we may, but I see the use to be fairly limited in that regard), but we will use the pack URI to point to proper image / icon / bitmap files - so it's nice if we can consolidate all those files into a single DLL.

posted @ Monday, April 28, 2008 1:41 PM | Feedback (1)
News