Saturday, September 18, 2010

WPF, Prism, and Creating Dynamic Menus - Part 2

Continuing my post from last time...

So my question on StackOverflow ended up getting a great answer that worked perfectly.  Where did I go wrong?

I listened to advice on teh internets (and I'm still learning WPF, which, if I knew it better, would have precluded me from going down this wonky path at all).  The "path" I ended up going down had a dynamic menu being created in a HierarchicalDataTemplate (good), but the actual content of the menu being generated in a load event in the code-behind (bad).

It's not that I'm against code in the code-behind.  I think there are times where it does make sense - take click event handlers in a ListView, for example.  There isn't a great way to route that through an ICommand object, at least that I'm aware of.  Often you aren't going to really do anything in the click handler - you just need to pass it back to the PresentationModel / ViewModel, which has all the logic to do the action of the click anyway.  You just need to handle the click.  And, unlike a menu, toolbar, or other button, you probably have a one-to-one relationship between the click handler and the method in PM/VM that will handle the action (so the benefit of an ICommand object is lessened somewhat).  Anyway.

That rant over, I pretty much knew I was hosing myself when I had written this blob of code:





private void ContentPresenter_Loaded(object sender, System.Windows.RoutedEventArgs e)
{

   ContentPresenter presenter = sender as ContentPresenter;

   if (sender != null)
   {
      DependencyObject parentObject = VisualTreeHelper.GetParent(presenter);
      bool bContinue = true;

      while (bContinue
         || parentObject == null)
      {
         if (parentObject is MenuItem)
            bContinue = false;
         else
            parentObject = VisualTreeHelper.GetParent(parentObject);
      }
      var menuItem = parentObject as MenuItem;

      if (menuItem != null)
      {

         ToolbarObject toolbarObject = menuItem.DataContext as ToolbarObject;
         StackPanel panel = new StackPanel();
         if (!String.IsNullOrEmpty(toolbarObject.ImageLocation))
         {
            Image image = new Image();
            image.Height = 24;
            image.VerticalAlignment = System.Windows.VerticalAlignment.Center;

            Binding sourceBinding = new Binding("ImageLocation");
            sourceBinding.Mode = BindingMode.TwoWay;
            sourceBinding.Source = toolbarObject;

            image.SetBinding(Image.SourceProperty, sourceBinding);

            panel.Children.Add(image);

         }

         ContentPresenter contentPresenter = new ContentPresenter();
         Binding contentBinding = new Binding("Name");
         contentBinding.Mode = BindingMode.TwoWay;
         contentBinding.Source = toolbarObject;
         contentPresenter.SetBinding(ContentPresenter.ContentProperty,
            contentBinding);
        
         panel.Children.Add(contentPresenter);

         menuItem.Header = panel;

         Binding commandBinding = new Binding("Command");
         commandBinding.Mode = BindingMode.TwoWay;
         commandBinding.Source = toolbarObject;
         menuItem.SetBinding(MenuItem.CommandProperty, commandBinding);
      }
   }
}


Yeah, that's no good at all. The end result of this was a "blank" menu, where the non-rendered items were clickable, but no rendering was done on the StackPanel embedded in the MenuItem's Header. Close, but no cigar.

Luckily, you can handle this pretty easily using the ItemContainerStyle property of a HierarchicalDataTemplate.  (I added the additional Style directive to handle the case where the command needs to occur on an item in the first row of the Menu)



<UserControl.Resources>

   <model:RecapToolBarPresentationModel x:Key="modelData" />
   <Style TargetType="MenuItem">
      <Setter Property="Command" Value="{Binding Path=Command}"/>
   </Style>
   <HierarchicalDataTemplate DataType="{x:Type model:ToolbarObject}"
      ItemsSource="{Binding Path=Children}">
      <HierarchicalDataTemplate.ItemContainerStyle>
         <Style TargetType="MenuItem">
            <Setter Property="Command" Value="{Binding Path=Command}"/>
         </Style>
      </HierarchicalDataTemplate.ItemContainerStyle>
      <StackPanel VerticalAlignment="Top" Margin="5,0,5,0">
         <Image Height="24" VerticalAlignment="Center" Source="{Binding Path=ImageLocation}"/>
         <ContentPresenter Content="{Binding Path=Name}" HorizontalAlignment="Center"/>
      </StackPanel>
   </HierarchicalDataTemplate>
</UserControl.Resources>



Lessons Learned:
  1. I've got a lot to learn in WPF still.  Knowing enough to get some basic ListViews displayed (and enough to get Prism more or less working for me) is great and all, but the more complex DataTemplating is still a learning ground.  Good stuff though - the power of WPF when compared against WinForms (or worse, MFC) is simply astounding.
  2. Watch out for advice coming teh internets.  StackOverflow's ratings really do provide a nice level of confidence on the advice you get (which, incidentally, you certainly aren't getting by reading this blog)

Friday, September 17, 2010

WPF, Prism, and Creating Dynamic Menus

This blog post originated from a question on StackOverflow How to programmatically set MenuItem.Header in a dynamic menu that I asked.  The first (and currently, only) person responding to the question implied that they weren't sure how I ended up where I did.  In order to clarify, I decided to write up this post (first one in what, a year?)

I've been working for sometime now on an application that utilizes WPF and Prism. Originally, the application had a static menu hosted in a seperate module - when the user clicked an item in the menu, static CompositeCommand objects would route command data back to a presentation model where DelegateCommands would handle the events.  This was an easy thing to knock together, as shown below.

The Original

PresentationModel

The original code behind the PresentationModel (or ViewModel - I started off with PresentationModel, even though VM is probably a better way of stating it - for consistency's sake, I'm going to stick with PM):



public interface IToolBarPresentationModel
{
   /// <summary>
   /// View associated with this model
   /// </summary>
   IToolBarView View { get; set; }
}

internal sealed class ToolBarPresentationModel : IToolBarPresentationModel
{
   private readonly IUnityContainer _container;
   private readonly IEventAggregator _eventAggregator;
   public DelegateCommand<object> FileExitCommand { get; set; }
   public DelegateCommand<object> HelpCommand { get; set; }

   /// <summary>
   /// Default constructor
   /// </summary>
   /// <param name="container">The unity container</param>
   /// <exception cref="ArgumentNullException">Thrown if the container is null</exception>
   public ToolBarPresentationModel(IUnityContainer container, IEventAggregator eventAggregator)
   {
      if (container == null)
         throw new ArgumentNullException("container", "The IUnityContainer cannot be null");
      if (eventAggregator == null)
         throw new ArgumentNullException("eventAggregator", "The IEventAggregator cannot be null");

      _container = container;
      _eventAggregator = eventAggregator;

      View = _container.Resolve<IToolBarView>();
      View.Model = this;

      FileExitCommand = new DelegateCommand<object>(new Action<object>(OnFileExit));
      HelpCommand = new DelegateCommand<object>(new Action<object>(OnHelp));

      ToolBarCommands.FileExit.RegisterCommand(this.FileExitCommand);
      ToolBarCommands.Help.RegisterCommand(this.HelpCommand);
   }
}

   private void OnFileExit(Object obj)
   {
      Application.Current.Shutdown();
   }

   private void OnHelp(Object obj)
   {
      var presentationModel = _container.Resolve<IHelpPresentationModel>();
      // Notify that the help view should be shown
      _eventAggregator.GetEvent<ChangeViewEvent>().Publish(new ChangeViewEventArguments(ViewName.HelpView));
   }

   #region IToolBarPresentationModel Members

   public Modules.ToolBar.Views.IToolBarView View
   {
      get;
      set;
   }

   #endregion
}

This is fairly straight-forward. We have two commands - File->Exit and Help, each of which have a static CompositeCommand that we add our DelegateCommand objects to. The Action targets exit the application, and call an event that forces the Help view to be displayed.

View

The original code behind simply implemented the View's interface:


public interface IToolBarView
{
   /// <summary>
   /// The model associated with this view
   /// </summary>
   IToolBarPresentationModel Model { get; set; }


The XAML was almost equally vanilla - except for one small detail that ended up being the crux of the problem:


<UserControl x:Class="Modules.ToolBar.Views.ToolBarView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:model="clr-namespace:Modules.ToolBar.PresentationModels"
xmlns:local="clr-namespace:Modules.ToolBar">
<Grid>
   <Menu Height="48" Margin="5,0,5,0" Name="MainMenu" VerticalAlignment="Top" Background="Transparent"
ItemsSource="{Binding}">
      <MenuItem Name="MenuFile" AutomationProperties.AutomationId="File">
         <MenuItem.Header>
            <StackPanel>
               <Image Height="24" VerticalAlignment="Center" Source="../Resources/066.png"/>
               <ContentPresenter Content="Main"/>
            </StackPanel>
         </MenuItem.Header>
         <MenuItem AutomationProperties.AutomationId="FileExit" Command="{x:Static local:ToolBarCommands.FileExit}">
            <MenuItem.Header>
               <StackPanel>
                  <Image Height="24" VerticalAlignment="Center" Source="../Resources/002.png"/>
                  <ContentPresenter Content="Exit"/>
               </StackPanel>
            </MenuItem.Header>
         </MenuItem>
      </MenuItem>
      <MenuItem Name="MenuHelp" AutomationProperties.AutomationId="Help" Command="{x:Static local:ToolBarCommands.Help}">
         <MenuItem.Header>
            <StackPanel>
               <Image Height="24" VerticalAlignment="Center" Source="../Resources/152.png"/>
               <ContentPresenter Content="Help"/>
            </StackPanel>
         </MenuItem.Header>
      </MenuItem>
   </Menu>
</Grid>
</UserControl>


The part of this XAML layout of the menu that I liked in the first cut was the appearance of each <MenuItem> - the <StackPanel> surrounding the <Image> and <ContentPresenter> lays out content such that it has sort of a "poor man's Ribbon" look and feel to it.

So: the goal is to keep the original look and feel of the menu, while updating it with the capability to have other modules add items to the menu.  The first cut!

Attempt One

So the first attempt had me adding a new model class that would represent a single item in the menu, called ToolbarObject - shown below.



/// <summary>
/// Represents an object on the toolbar
/// </summary>

public sealed class ToolbarObject : INotifyPropertyChanged
{

   public ToolbarObject() : this(String.Empty, String.Empty, null)
   {

   }
   public ToolbarObject(
      String name,
      String imageLocation,
      CompositeCommand command)
   {
      _name = name;
      _imageLocation = imageLocation;
      _command = command;
      Children = new ObservableCollection();
   }

   private String _name;
   public String Name
   {
      get { return _name; }
      set
      {
         _name = value;
         NotifyPropertyChanged("Name");
      }
   }

   private string _imageLocation;
   public String ImageLocation
   {
      get
      {
         return _imageLocation;
      }
      set
      {
         _imageLocation = value;
         NotifyPropertyChanged("ImageLocation");
      }
   }

   private CompositeCommand _command;
   public CompositeCommand Command
   {
      get
      {
         return _command;
      }
      set
      {
         _command = value;
         NotifyPropertyChanged("Command");
      }
   }

   private ObservableCollection _children;
   public ObservableCollection Children
   {
      get
      {
         return _children;
      }
      set
      {
         _children = value;
      }
   }
  
   #region INotifyPropertyChanged Members
      public event PropertyChangedEventHandler PropertyChanged;
   #endregion

   private void NotifyPropertyChanged(String name)
   {
      PropertyChangedEventHandler handler = PropertyChanged;
      if (!String.IsNullOrEmpty(name)
         && handler != null)
      {
         handler(this, new PropertyChangedEventArgs(name));
      }
   }
}


Since I now have an object representing the menu, the PresentationModel was updated with an ObservableCollection of ToolbarItems - shown in the following (just showing the interface, as the implementation doesn't need explanation):



public interface IToolBarPresentationModel
{

/// <summary>
/// View associated with this model
/// </summary>

IToolBarView View { get; set; }

ObservableCollection<ToolbarObject> ToolbarItems { get; set; }

}


The view was updated to use a hierarchical data template, and the menu was bound to the data template and the new observable collection:


<UserControl x:Class="Modules.ToolBar.Views.ToolBarView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:model="clr-namespace:Modules.ToolBar.PresentationModels"
xmlns:local="clr-namespace:Modules.ToolBar">
   <UserControl.Resources>
      <model:ToolBarPresentationModel x:Key="modelData" />
      <HierarchicalDataTemplate DataType="{x:Type model:ToolbarObject}"
         ItemsSource="{Binding Path=Children}">
         <MenuItem Command="{Binding Path=Command}">
            <MenuItem.Header>
               <StackPanel>
                  <Image Height="24" VerticalAlignment="Center" Source="{Binding Path=ImageLocation}"/>
                  <ContentPresenter Content="{Binding Path=Name}"/>
               </StackPanel>
            </MenuItem.Header>
         </MenuItem>
      </HierarchicalDataTemplate>
    </UserControl.Resources>
<UserControl.DataContext>
    <Binding Source="{StaticResource modelData}"/>
</UserControl.DataContext>
<Grid>
   <Menu Height="48" Margin="5,0,5,0" Name="MainMenu" VerticalAlignment="Top" Background="Transparent"
ItemsSource="{Binding}">
   </Menu>
</Grid>
</UserControl>


This does a great job of rendering the first row in the menu - however, although the command routing works, the images are shown for the first items in the menu, any subitems aren't shown. Clicking on "File", for example, wouldn't collapse any submenu. In researching this, I came across two articles:

Building a Databound WPF Menu using a HierarchicalDataTemplate

WPF Sample Series - DataBound HierarchicalDataTemplate Menu Sample

In these examples, the code behind is responsible (in a load event) for constructing the hiearchy in the menu and ensuring that everything gets bound together correctly.  When this is just a menu, this works great - however, the moment you try to place the <StackPanel> into the <MenuItem.Header>, the whole thing doesn't get rendered (it is clickable, however).  The question on StackOverflow thus became the following:
  1. Admittedly, there is a "code-smell" in using the code-behind to construct what should just be a HierarchicalDataTemplate.  Is there a way to do this that doesn't involve the load event?
  2. If not, then how can you get the rendering of items placed into a MenuItem's Header to work?  What is preventing them from being drawn?
When I get more of a conclusion, I'll update this with the version that uses the advice in the menus and the actual solution (I'm confident there is a way to do this that isn't too ugly).  For now, the XAML and code-behind showing my version of the menu construction in the load event is available on the StackOverflow question here.

Sunday, January 17, 2010

Test 1 ... 2


public class Something
{
  private int _nSomethingElse;

  public Something()
  {
  }

  public int SomethingElse
  {
    get { return _nSomethingElse; }
    set { _nSomethingElse = value; }
  }
}

Wednesday, January 7, 2009

Order of Operations and the Undefined Behavior

Recently I came across a topic on Stack Overflow that intrigued me. The question was thus:
Can someone explain to me why this code prints 14? I was just asked by another student and couldn't figure it out.


int i = 5;
i = ++i + ++i;
cout << i;


As it turns out, the equation
i = ++i + ++i;
is undefined in the C / C++ standard. The issue boils down to one of expression evaluation. If we look at just i = i++;, and if i++; is interpreted as i = i + 1;, then what is i = i = i + 1? What takes precedence in the assignment and the evaluation? Not too surprisingly, the creators of C / C++ simply resolved the issue with an "undefined" - the ISO equivalent of a punt. See Stroustrup's Explanation or the C++ Standard itself for more explanation. (Note that as Stroustrup points out, C++ more or less inherited this behavior from C).

But this made me curious: if C++ has this behavior as undefined, how does C# handle this same problem?

Let's look at a very simple case that is allowed by the C# compiler:


int i = 1;
i = (++i) + (++i);
System.Console.WriteLine(i);



Knowing that the above code my be undefined (which, by the way, I need to read the C# standard and find out if it really is undefined or not), I would anticipate that the output would be either 5 or 6. Let's look at both.

Scenario 1:
If it is 5, we would have a sequence similar to this:

i = (i++) + (2);
i = (3) + (2);
i = 5;


The above seems to assume that a temporary variable is used for either the pre- or post-increment operator, and then an addition is performed.

Scenario 2:
If, however, the output is 6, we would have a sequence similar to this:

i = (i++) + (2);
i = (3) + (3);
i = 6;


In this case, i is assigned to a value of 3 after the pre-increment operator, and the addition becomes i + i (as opposed to i + (prev)i, as it was for an output of 5).

Running the above code in C# however will output 5. It looks like Scenario 1 is the winner - but what happened?

To answer this, we can look at the IL generated for that snippet of code:


int i = 1;
000000ff mov dword ptr [ebp-4Ch],1
i = (++i) + (++i);
00000106 inc dword ptr [ebp-4Ch]
00000109 mov esi,dword ptr [ebp-4Ch]
0000010c inc dword ptr [ebp-4Ch]
0000010f add dword ptr [ebp-4Ch],esi
System.Console.WriteLine(i);
00000112 mov ecx,dword ptr [ebp-4Ch]
00000115 call 747E2EA0
0000011a nop



We store the original value in ebp. We then increment the value, and store it in esi. We then increment the value in ebp again, then add it to the value in esi. Note that while Scenario 1 here is the winner, the user on Stack Overflow got a result consistent with Scenario 2 with their C++ compiler... interesting!

Even more interesting is what we get if we use post-increment operators in the statement - that being 3.

int i = 1;
000000ff mov dword ptr [ebp-4Ch],1
i = i++ + i++;
00000106 mov edi,dword ptr [ebp-4Ch]
00000109 inc dword ptr [ebp-4Ch]
0000010c mov esi,dword ptr [ebp-4Ch]
0000010f inc dword ptr [ebp-4Ch]
00000112 add edi,esi
00000114 mov dword ptr [ebp-4Ch],edi
System.Console.WriteLine(i);
00000117 mov ecx,dword ptr [ebp-4Ch]
0000011a call 747E2EA0
0000011f nop


Here we store the value initially in ebp. We then store it in edi, and increment ebp. We move that value (2) to esi, and increment ebp again (3). We then add edi and esi together - and get 3. We then move edi to ebp.

Looking at the order of precedence in C# for the post-increment operator, it does make sense that the post-increment occurs prior to the addition - what is interesting is that the addition doesn't use both increments, but rather the original value of i (1) and the first post-increment result stored in esi. Odd.

Let's look at what happens if we use a mix of pre- and post-increment operators:


int i = 1;
000000ff mov dword ptr [ebp-4Ch],1
i = (i++) + (++i);
00000106 mov esi,dword ptr [ebp-4Ch]
00000109 inc dword ptr [ebp-4Ch]
0000010c inc dword ptr [ebp-4Ch]
0000010f add dword ptr [ebp-4Ch],esi
System.Console.WriteLine(i);
00000112 mov ecx,dword ptr [ebp-4Ch]
00000115 call 747E2EA0
0000011a nop


This will actually give you an output of 4. We declare i and store it in ebp. When we reach our i = (i++) + (++i); statement, we store the value of i in register esi. So far, so good. The next two instructions increment the value of i - at this point, I would expect the output of the statement to be 5 or 6, right? Instead, C# does something odd here, and adds it to the original value of i stored in esi. Not at all what I would expect - except, again, that pre- and post-increment operators do not have the same order of precedence. In this case, it appears as if what we are really calculating is i = i + (++(i++)), or i = i + ((i+1))+1).

Moral of the Story

  1. Undefined operations can have interesting results. I haven't searched the C# specification for whether or not this really is undefined in C# (I imagine I probably should do that!) - but either way, people should be careful using what is undefined in one language in a different language as well.
  2. There really is a difference between pre- and post-increment, and order of precedence matters a lot (unless, of course, 3 == 4 == 5).

Friday, January 2, 2009

And so it begins...

I won't claim that this is the first blog / weblog / online posting I've ever created. As with all my previous attempts at writing something interesting in a web environment, I don't have very high hopes that it will last much longer than a few months.

As an aside, I hate having to come up with titles. I'm not very good at it; I think I try to get too creative and end up with something that, quite frankly, sounds a bit smarmy. I probably did the same thing here - "Dynamic Reconfiguration" - my only excuse is that it was available. Loosely, Dynamic Reconfiguration refers to an area of research (with some implementations here and there) where hardware is able to adapt itself at run-time to the problems its required to solve. Dynamic Reconfiguration was a driving interest in my research for my master's; but, as is true with most people who pursue graduate degrees, its role in my life is now relegated to an interesting sidenote on my CV. Oh well.