... a journey through WPF, MVVM and .NET4 RSS 2.0
# Wednesday, April 01, 2009

One annoying thing about ObservableCollection<T> is that it doesn't support modifications from background threads.  That is to say, the CollectionChanged notification doesn't marshal to the proper thread when it is raised and it causes the exception "This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread". 

I ran into this problem a while back and searched out to see if someone else had solved it. I found a solution from Tamir Khason (a fellow WPF disciple), he wrote a thread-safe version (http://blogs.microsoft.co.il/blogs/tamir/archive/2007/04/22/Thread-safe-observable-collection.aspx), but I didn't want to add the locking into the collection itself (I want to manage it at a higher level myself).  Really, all I want is to do the notification on the proper (Dispatcher) thread. 

It turns out to be pretty easy, here's my solution:

public class MTObservableCollection<T> : ObservableCollection<T>
{
   public override event NotifyCollectionChangedEventHandler CollectionChanged;
   protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
   {
      var eh = CollectionChanged;
      if (eh != null)
      {
         Dispatcher dispatcher = (from NotifyCollectionChangedEventHandler nh in eh.GetInvocationList()
                 let dpo = nh.Target as DispatcherObject
                 where dpo != null
                 select dpo.Dispatcher).FirstOrDefault();

        if (dispatcher != null && dispatcher.CheckAccess() == false)
        {
           dispatcher.Invoke(DispatcherPriority.DataBind, (Action)(() => OnCollectionChanged(e)));
        }
        else
        {
           foreach (NotifyCollectionChangedEventHandler nh in eh.GetInvocationList())
              nh.Invoke(this, e);
        }
     }
  }
}

Wednesday, April 01, 2009 12:17:37 PM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | WPF
# Thursday, March 05, 2009

A couple of weeks ago, Jason Whittington (a fellow instructor at Developmentor) and I were doing a talk on asynchronous programming and we started with a very simple example of the APM -- using two loops to create and then consume the IAsyncResult work:

static void TwoLoopMain(string[] args)
{
   Queue<IAsyncResult> ars = new Queue<IAsyncResult>();
   Func<int,int,int> mathProc = Multiply;

   for (int i = 1; i <= 20; i++)
   {
      for (int j = 1; j <= 20; j++)
         ars.Enqueue(mathProc.BeginInvoke(i, j, null, null));
   }
   for (int i = 1; i <= 20; i++)
   {
      for (int j = 1; j <= 20; j++)
      {
         int result = mathProc.EndInvoke(ars.Dequeue());
         Console.SetCursorPosition(i * 3, j);
         Console.Write(result);
     }
  }
}

We had already presented a talk on LINQ earlier in the week and so I thought we might be able to do the above in a single expression with LINQ - kind of a challenge .. here's what we came up with:

static void LinqTest()
{
   Func<int,int,int> mathProc = Multiply;

   (from i in Enumerable.Range(1, 20)
    from j in Enumerable.Range(1, 20)
    select new { i, j, ar = mathProc.BeginInvoke(i, j, null, null) })
      .ToList()
      .ForEach(e => {
        int result = mathProc.EndInvoke(e.ar);
        Console.SetCursorPosition(e.i * 3, e.j);
        Console.Write(result);
     });
}

It's not easily readable (and so I wouldn't promote this for production code), but it's way cool and an example of how LINQ (and functional programming in general) is really changing the way programmers think about code.. just freaking cool..

Thursday, March 05, 2009 11:27:19 AM (Central Standard Time, UTC-06:00)  #    Comments [0] -
.NET
# Monday, February 23, 2009

I use a lot of virtual machines - and it's always handy to store files onto the real machine through shared folders. With Windows 7 and the new library feature I thought it would be really cool to add the shares to the Documents Library but found that the underlying system must be running Indexing Server 4.0 -- not an option for my OSX based system!

Here's a nice little workaround that lets you add non-indexed folders though:

To add a non-indexed UNC as a library to Windows 7 Beta:

1. Create a folder on your hard drive for shares. I used c:\users\Mark\Shares\Documents.
2. Add the new folder to your library using Explorer.
3. Delete the folder using a command prompt window.
4. Use the mklink command to create a symbolic link with the Documents name to your share. In my case the proper command was:

mklink /D Documents \\.Host\Documents

Note that mklink.exe requires administrator access so start the command prompt by holding SHIFT+CTRL and clicking on it (or use the "Run As Administrator" option)


Voila! Explorer keeps the folder in the library even though it's not indexed.
Monday, February 23, 2009 8:33:36 PM (Central Standard Time, UTC-06:00)  #    Comments [0] -

# Thursday, January 29, 2009
Update
Microsoft has released the API code pack including Windows 7 support -- get it here: http://code.msdn.microsoft.com/WindowsAPICodePack

Well, it's been a while since I posted anything, I'm sorry!

I've been busy working with Windows 7 and Microsoft Surface touch-computing. To that end, I needed to get access to some of the new Windows 7 APIs in managed code ... which isn't supported yet (but is coming).

So I built an interop library to access:

  • Scenic Ribbon (native Win32 ribbon) in Windows Forms
  •  Native WM_TOUCH and WM_GESTURE messages
  •  Sensor API
  •  Shell APIs (jump lists, thumbnail buttons, libraries)
One note: I make no guarantee that everything is correct (it's hard to do that on a shifting beta with minimal docs, but in addition I'm not sure I've gotten 100% coverage with everything anyway). Here's the interop library with source code:

Windows 7 Beta 1 Interop Library for .NET 2.0

I'll be posting more details and samples a bit later, here's a couple to get you started.

Here's a simple example of using the Scenic Ribbon and native touch support to create a (very) simple Windows Forms finger
 paint program:

touch_img.jpg

  Multi Touch example with Windows Forms

Here's a simple example of using the gestures and library support in a WPF application. It grabs all the directories in your Pictures Library and then shows you each picture and lets you use the swipe gesture to move between then, pinch to scale and of course, rotate.

gesture_img.jpg

Gesture example with WPF

Both of these samples work with the HP Touchmate (and multi-touch drivers) and Windows 7 Beta 1. Have fun! -mark
Thursday, January 29, 2009 12:02:21 PM (Central Standard Time, UTC-06:00)  #    Comments [0] -
.NET | Code | WPF
# Thursday, November 13, 2008

I've been playing with the Silverlight toolkit (released at PDC) this week and ran across a pretty nasty edge case related to HeaderedContentControl and the implicit style manager.  If you create something like this, where the Header is set to a Visual of some kind:

<UserControl x:Class="SilverlightPrototype.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    xmlns:Controls="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls">

<StackPanel x:Name="LayoutRoot" Background="White">
   <Button Click="Button_Click" Content="Change Style" />
   <Controls:HeaderedContentControl>
      <Controls:HeaderedContentControl.Header>
         <TextBlock Text="Header" Foreground="DarkBlue" FontWeight="Bold" />
      </Controls:HeaderedContentControl.Header>
      <TextBlock Text="Body" />
   </Controls:HeaderedContentControl>
</StackPanel>

</UserControl>

And then you change the style of the headered control when the button is clicked:

private void Button_Click(object sender, RoutedEventArgs e)
{            
    Uri uri = new Uri(@"SilverlightPrototype;component/theming/simplestyle.xaml", UriKind.Relative);
    ImplicitStyleManager.SetResourceDictionaryUri(LayoutRoot, uri);
    ImplicitStyleManager.SetApplyMode(LayoutRoot, ImplicitStylesApplyMode.OneTime);
    ImplicitStyleManager.Apply(LayoutRoot);
}

Where the style is just a simple ContentPresenter or ContentControl for the header and the body:

<Style TargetType="Controls:HeaderedContentControl">
   <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="Controls:HeaderedContentControl">
           <StackPanel Orientation="Horizontal">
              <ContentPresenter Content="{TemplateBinding Header}" ContentTemplate="{TemplateBinding HeaderTemplate}" Margin="10" />
              <ContentPresenter Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" Margin="10" />
           </StackPanel>
        </ControlTemplate>
     </Setter.Value>
   </Setter>
</Style>

Silverlight will crash deep in the DependencyProperty.SetValue code with an ArgumentException indicating that the TextBlock for the header is invalid.  The issue appears to be that the TextBlock defined as the header content is already part of the visual tree and therefore cannot be bound to the new control template.  Content works fine so there is some other path being taken for that property.

The workaround is pretty easy, just use a non-visual in the header and then supply a DataTemplate to give it the appropriate visual tree.  Silverlight will re-create the visual tree each time from the data template so we don't have the reuse issue:

<StackPanel x:Name="LayoutRoot" Background="White">

<StackPanel.Resources>
   <!-- Header works as long as template is supplied - i.e. non-visual element applied directly to header -->
   <DataTemplate x:Key="HeaderTemplate">
      <TextBlock Foreground="DarkBlue" FontWeight="Bold" Text="{Binding}" />
   </DataTemplate>
</StackPanel.Resources>

<Button Click="Button_Click" Content="Change Style" />

<Controls:HeaderedContentControl HeaderTemplate="{StaticResource HeaderTemplate}">
   <Controls:HeaderedContentControl.Header>
      <sys:String>Header Text</sys:String>
   </Controls:HeaderedContentControl.Header>

   <TextBlock Text="Body" />
</Controls:HeaderedContentControl>

</StackPanel>

If you need more than a string, then just define an object and assign that instead - for example:

class HeaderStuff
{
   public string Text { get; set; }
   public bool IsChecked { get; set; }
}

<DataTemplate x:Key="HeaderStuff">
   <StackPanel>
      <Rectangle Fill="Blue" Stroke="Yellow" Width="50" ... />
      <CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Text}" />
   </StackPanel>
</DataTemplate>

...

<Controls:HeaderedContentControl HeaderTemplate="{StaticResource HeaderStuff}">
   <Controls:HeaderedContentControl.Header>
      <me:HeaderStuff IsChecked="True" Text="This is a checkbox" />
   </Controls:HeaderedContentControl.Header>
</Controls:HeaderedContentControl.Header>


Thursday, November 13, 2008 9:42:01 AM (Central Standard Time, UTC-06:00)  #    Comments [0] -
.NET
# Wednesday, November 12, 2008
One of the coolest new debugging features included with VS2010 CTP1 is the management of WPF event traces directly in the IDE.  With this feature you can turn specific event traces on and off and have them show up in the debug window.  The default setting is to just show data binding errors - the existing behavior.  But now you can view resource lookups, routed event creation, etc. Here's the dialog:


Wednesday, November 12, 2008 1:06:04 PM (Central Standard Time, UTC-06:00)  #    Comments [0] -
.NET | WPF
# Thursday, October 02, 2008
Here are the demos for the guys who attended the 2-day binding + network Silverlight2 training in Boston.  Thanks guys!


Thursday, October 02, 2008 9:04:48 AM (Central Daylight Time, UTC-05:00)  #    Comments [0] -

# Monday, September 22, 2008
Thanks to all who attended - it was great to meet all of you and hang out until the wee hours and play Rock Band! 

Here are the demos from the class - I removed most of the binaries to bring it down to a reasonable size.

I also put the pictures online at Flickr

Thanks again everyone!


Monday, September 22, 2008 8:33:32 AM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | Code
# Friday, September 12, 2008

One thing that's kind of cool in WPF is that you can use brushes to fill almost anything and that there are some really cool brushes in the toolkit.  It always blows people away when you show them a piece of text filled with a live video complements of a Visual Brush.

 

But, unfortunately text doesn't have a stroke property - only a fill so you can't add an edge to it.  You can layer another piece of text under it, but often it doesn't quite match up size-wise when you do this.  The solution is to convert the text to a Path which has both a fill and stroke and it turns out it's pretty easy to do.

 

If you just have one piece of text you are better off using Blend's "Convert to Path" option -- it will do the one-time conversion for you and you can just insert the shape into your UI.  If you have more than one element though it can be tedious, and it doesn't work at all for dynamic pieces of text - that's where this TextPath class comes in handy.   With it you can create text like this:

 

 

Notice how the text is outlined in a different color -- any brush could be used so you could do wacky things like have the "WPF" part be ringed in fire (using the Dreamscene fire video for example). 

 

The class is dead simple to use, it's a Shape class so you can simply insert it right into your XAML and set the font properties and text:


 

<StackPanel Orientation="Horizontal" TextElement.FontWeight="Bold" TextElement.FontSize="72pt">
       
<me:TextPath FontFamily="Consolas,Courier New" Margin="5" Text="WPF"
                      
StrokeThickness="3" Fill="Gold" Stroke="Red" /> 
        
<me:TextPath FontFamily="Balloon" Margin="5" Text="Rocks" StrokeThickness="3" Stroke="Black">
          
<me:TextPath.Fill>
             
<ImageBrush ImageSource="rocks.jpg" />
           
</me:TextPath.Fill>
       
</me:TextPath>
</StackPanel>

 

Notice it uses the same font dependency properties as all other text-based framework elements - that allows us to inherit the property values which is useful. 

 

Here's the sample project which full source code:  OutlineTextTest.zip (1.54 MB)

Friday, September 12, 2008 10:52:21 PM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | WPF

We've seen how to programatically control focus and that's all great stuff, but one thing I like to do with WPF is see how much of the repetitive or UI-specific code I can move into the XAML and keep out of the code behind.  We can use the FocusManager.FocusedElement property to shift focus in XAML but it only works when the element exists in the main XAML file.  If you use UserControls it turns out that the approach doesn't work because that element is loaded separately and not available when the initial focus is being determined.

In my specific case, I have a wizard-style application which utilizes a TabControl to move between the pages.  The first page looks like this:

The XAML layout for window1.xaml looks something like this:

<TabControl x:Name="Pages" SelectedIndex="0">
   <FocusTest:Page1 />
   <FocusTest:Page2 />
   <FocusTest:FinalPage />
</TabControl>

What I want is to have focus immediately positioned within the first text box but it turns out that you can't get WPF to do this directly from XAML - because the TextBox isn't a direct descendent of Window - it's part of the Page1 user control.  You can try putting the focus shift into the user control but it turns out that it won't work there either - it's got to be assigned to the focus scope which is the window.

So it might seem we are stuck with adding code behind logic (blech!) but all is not lost!  When I hit situations like this, I try to think about how to solve the problem generically so I can reuse my solution.  In this case, I decided to build a MarkupExtension to locate the first focusable element descendent.

If you are not familiar with markup extensions, they are a corner piece in the XAML extensibility story.  They allow for dynamic property assignment - where the value is determined at runtime vs. XAML compile time.  That's exactly what I need here - I want to find that TextBox at runtime and shift focus to it - just like I would have done in the code behind.

Creating a markup extension is trivial - you just extend the MarkupExtension base class and implement the ProvideValue method.  In this case, when provide value is called, I have to do several steps:

  1. If the element we are bound to is not loaded yet, we need to wait for it.  We won't be able to find the child in the visual tree if the parent isn't yet loaded.
  2. Once it is loaded, search the children and find the first control we can give focus to.  That means, the control is visible, focusable and enabled.
  3. Assign logical focus to the new control in the closest focus scope parent, or just return the value if the property being assigned to is not FocusManager.FocusedElement.

I decided to try to make a generic markup extension that could be used outside my scenario so I added a little bit of code to see if we are assigning to FocusManager.FocusedElement and act differently in that specific case - otherwise the extension just returns the value.

With this new extension, I can now add a single line of code to each user control:

<UserControl x:Class="FocusTest.Page2"
   xmlns:FocusTest="clr-namespace:FocusTest"
   FocusManager.FocusedElement="{FocusTest:FirstFocusedElement}">

Now, when I run the application, focus is always assigned to the first control it can be assigned to.  It turns out that I can go one step better and always assign focus when the page becomes visible in my wizard - remember we have to wait for the control to finish loading to find the element.. this is done by hooking the FrameworkElement.Loaded event.  This event is raised each time the TabControl shifts to a new tab - so if we never unhook our handler, our focus management code is called each time the tab page becomes visible.  This might not be the required behavior so I added a simple property to the markup extension called OneTime to control that behavior.

There's a bit too much code to blog here, but if you want to try this out yourself, here's the test project.. feel free to use this however you like.  FocusTest.zip (17.88 KB)

Update: Andrew Smith pointed out that the code would assign focus to a focus scope if it ran across one - which could happen if you have a toolbar or menu present in the UI.  I didn't in the sample (or in my production app) but I could certainly see that being a common reality.  I changed the above code to deliberately skip focus scopes and their children and keep going down the tree until it finds the first child.  Thanks Andrew!

Friday, September 12, 2008 7:49:20 AM (Central Daylight Time, UTC-05:00)  #    Comments [0] -
.NET | WPF
I'm a WPF Disciple
Search
Categories
Archive
<April 2009>
SunMonTueWedThuFriSat
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2010
Mark Smith
Sign In
All Content © 2010, Mark Smith
DasBlog theme 'Business' created by Christoph De Baene (delarou)