Click here to Skip to main content
Click here to Skip to main content

Selector DoubleClick Behaviour calling ViewModel ICommand

By , 8 Sep 2009
 

The other day I was at work and needed to use a WPF ListView (Selector) to call an ICommand in a ViewModel. Nown we want to be good and use nice design approaches, so I thought about using the attached command capabilities of my Cinch MVVM framework. But then I thought, ah, I only want to call the ICommand when the user actually double clicks an Item in the ListView (Selector) and not when the double click occurs anywhere else, like say a header, which the ListView certainly has.

So without further ado, I set to work and came up with the following attached Behaviour DP:

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Windows;
   4:  using System.Windows.Controls.Primitives;
   5:  using System.Windows.Input;
   6:  using System.Windows.Controls;
   7:   
   8:  namespace ListViewDoubleCLick
   9:  {
  10:      /// <summary>
  11:      /// Selector MouseDoubleClick calling ViewModel ICommand  
  12:      /// </summary>
  13:      public static class SelectorDoubleClickCommandBehavior
  14:      {
  15:          #region Attached DPs
  16:          #region HandleDoubleClick
  17:   
  18:          /// <summary>
  19:          /// HandleDoubleClick Attached Dependency Property
  20:          /// </summary>
  21:          public static readonly DependencyProperty 
  22:              HandleDoubleClickProperty =
  23:              DependencyProperty.RegisterAttached(
  24:              "HandleDoubleClick", 
  25:              typeof(bool), 
  26:              typeof(SelectorDoubleClickCommandBehavior),
  27:                  new FrameworkPropertyMetadata(false,
  28:                      new PropertyChangedCallback(
  29:                          OnHandleDoubleClickChanged)));
  30:   
  31:          /// <summary>
  32:          /// Gets the HandleDoubleClick property.  
  33:          /// </summary>
  34:          public static bool GetHandleDoubleClick(DependencyObject d)
  35:          {
  36:              return (bool)d.GetValue(HandleDoubleClickProperty);
  37:          }
  38:   
  39:          /// <summary>
  40:          /// Sets the HandleDoubleClick property. 
  41:          /// </summary>
  42:          public static void SetHandleDoubleClick(DependencyObject d, 
  43:              bool value)
  44:          {
  45:              d.SetValue(HandleDoubleClickProperty, value);
  46:          }
  47:   
  48:          /// <summary>
  49:          /// Hooks up a weak event against the source Selectors 
  50:          /// MouseDoubleClick if the Selector has asked for 
  51:          /// the HandleDoubleClick to be handled
  52:          /// 
  53:          /// If the source Selector has expressed an interest 
  54:          /// in not having its MouseDoubleClick handled 
  55:          /// the internal reference
  56:          /// </summary>
  57:          private static void OnHandleDoubleClickChanged(
  58:              DependencyObject d,
  59:              DependencyPropertyChangedEventArgs e)
  60:          {
  61:              Selector selector = d as Selector;
  62:   
  63:   
  64:              if (selector != null)
  65:              {
  66:                  if ((bool)e.NewValue)
  67:                  {
  68:                      selector.MouseDoubleClick -= OnMouseDoubleClick;
  69:   
  70:                      //This will cause the MouseButtonEventHandler.Target
  71:                      //to keep a strong reference to the source of the
  72:                      //event, which will stop it from being GCd
  73:                      selector.MouseDoubleClick += OnMouseDoubleClick;
  74:                  }
  75:              }
  76:          }
  77:          #endregion
  78:   
  79:          #region TheCommandToRun
  80:   
  81:          /// <summary>
  82:          /// TheCommandToRun : The actual ICommand to run
  83:          /// </summary>
  84:          public static readonly DependencyProperty TheCommandToRunProperty =
  85:              DependencyProperty.RegisterAttached(
  86:                  "TheCommandToRun",
  87:                  typeof(ICommand),
  88:                  typeof(SelectorDoubleClickCommandBehavior),
  89:                  new FrameworkPropertyMetadata((ICommand)null));
  90:   
  91:          /// <summary>
  92:          /// Gets the TheCommandToRun property.  
  93:          /// </summary>
  94:          public static ICommand GetTheCommandToRun(DependencyObject d)
  95:          {
  96:              return (ICommand)d.GetValue(TheCommandToRunProperty);
  97:          }
  98:   
  99:          /// <summary>
 100:          /// Sets the TheCommandToRun property.  
 101:          /// </summary>
 102:          public static void SetTheCommandToRun(DependencyObject d, 
 103:              ICommand value)
 104:          {
 105:              d.SetValue(TheCommandToRunProperty, value);
 106:          }
 107:          #endregion
 108:          #endregion
 109:   
 110:          #region Private Methods
 111:   
 112:   
 113:          /// <summary>
 114:          /// Handle Selector.MouseDoubleClick but will 
 115:          /// only fire the associated ViewModel command 
 116:          /// if the MouseDoubleClick occurred over an actual
 117:          /// ItemsControl item. This is nessecary as if we 
 118:          /// are using a ListView we may have clicked the 
 119:          /// headers which are not items, so do not want the
 120:          /// associated ViewModel command to be run
 121:          /// </summary>
 122:          private static void OnMouseDoubleClick(object sender, 
 123:              MouseButtonEventArgs e)
 124:          {
 125:              //Get the ItemsControl and then get the item, and 
 126:              //check there is an actual item, as if we are using 
 127:              //a ListView we may have clicked the
 128:              //headers which are not items
 129:              ItemsControl listView = sender as ItemsControl;
 130:              DependencyObject originalSender = 
 131:                  e.OriginalSource as DependencyObject;
 132:              if (listView == null || originalSender == null) return;
 133:   
 134:              DependencyObject container = 
 135:                  ItemsControl.ContainerFromElement
 136:                  (sender as ItemsControl, 
 137:                  e.OriginalSource as DependencyObject);
 138:   
 139:              if (container == null || 
 140:                  container == DependencyProperty.UnsetValue) return;
 141:   
 142:              // found a container, now find the item.
 143:              object activatedItem = 
 144:                  listView.ItemContainerGenerator.
 145:                      ItemFromContainer(container);
 146:   
 147:              if (activatedItem != null)
 148:              {
 149:                  ICommand command = 
 150:                      (ICommand)(sender as DependencyObject).
 151:                      GetValue(TheCommandToRunProperty);
 152:   
 153:                  if (command != null)
 154:                  {
 155:                      if (command.CanExecute(null))
 156:                          command.Execute(null);
 157:                  }                
 158:              }
 159:          }
 160:          #endregion
 161:      }
 162:   
 163:  }

Where we would use this in XAML:

   1:  <Window x:Class="ListViewDoubleCLick.Window1"
   2:      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:      xmlns:local="clr-namespace:ListViewDoubleCLick"
   5:      xmlns:interactivity="clr-       namespace:Microsoft.Expression.Interactivity;
   6:         assembly=Microsoft.Expression.Interactivity" 
   7:      Title="Window1" Height="600" Width="800" 
   8:      WindowStartupLocation="CenterScreen">
   9:      <Grid>
  10:   
  11:          <TabControl>
  12:              <TabItem Header="Attached DP Approach">
  13:                  <ListView ItemsSource="{Binding People}"
  14:                    IsSynchronizedWithCurrentItem="True"
  15:                    local:NaiveSelectorDoubleClickCommandBehavior.HandleDoubleClick="true"
  16:                    local:NaiveSelectorDoubleClickCommandBehavior.TheCommandToRun=
  17:                            "{Binding Path=DoItCommand}" >
  18:   
  19:                      <ListView.View>
  20:                          <GridView>
  21:                              <GridViewColumn Header="FirstName"
  22:                                      DisplayMemberBinding="{Binding FirstName}"
  23:                                      Width="80" />
  24:                              <GridViewColumn Header="LastName" 
  25:                                      DisplayMemberBinding="{Binding LastName}"  
  26:                                      Width="80"/>
  27:                          </GridView>
  28:                      </ListView.View>
  29:                  </ListView>
  30:              </TabItem>
  31:          </TabControl>
  32:      </Grid>
  33:   
  34:  </Window>

Or, we could get really fancy and use the Blend 3 Microsoft.Expression.Interactivity.Dll, which would look something like this:

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Windows;
   4:  using System.Windows.Controls.Primitives;
   5:  using System.Windows.Input;
   6:  using System.Windows.Controls;
   7:  using Microsoft.Expression.Interactivity;
   8:  using System.ComponentModel;
   9:   
  10:  namespace ListViewDoubleCLick
  11:  {
  12:      /// <summary>
  13:      /// Selector MouseDoubleClick calling ViewModel ICommand Behavior
  14:      /// using Blend3 Microsoft.Expression.Interactivity Dll
  15:      /// </summary>
  16:      public class InteractionsSelectorDoubleClickCommandAction :
  17:          TargetedTriggerAction<FrameworkElement>,
  18:          ICommandSource
  19:      {
  20:          #region DPs
  21:   
  22:          #region Command DP
  23:          /// <summary>
  24:          /// The actual Command to fire when the 
  25:          /// EventTrigger occurs, thus firing this 
  26:          /// InteractionsSelectorDoubleClickCommandAction
  27:          /// </summary>
  28:          [Category("Command Properties")]
  29:          public ICommand Command
  30:          {
  31:              get { return (ICommand)GetValue(CommandProperty); }
  32:              set { SetValue(CommandProperty, value); }
  33:          }
  34:   
  35:          public static readonly DependencyProperty CommandProperty =
  36:              DependencyProperty.Register(
  37:                  "Command", typeof(ICommand),
  38:                      typeof(InteractionsSelectorDoubleClickCommandAction),
  39:                      new PropertyMetadata(
  40:                          (ICommand)null, OnCommandChanged));
  41:   
  42:          private static void OnCommandChanged(DependencyObject d,
  43:              DependencyPropertyChangedEventArgs e)
  44:          {
  45:              var action = 
  46:                  (InteractionsSelectorDoubleClickCommandAction)d;
  47:              action.OnCommandChanged((ICommand)e.OldValue, 
  48:                  (ICommand)e.NewValue);
  49:          }
  50:   
  51:          #region Command implementation
  52:   
  53:          /// <summary>
  54:          /// This is a strong reference to the Command.
  55:          /// CanExecuteChanged event handler. 
  56:          /// The commanding system uses a weak 
  57:          /// reference and if we don’t enforce a 
  58:          /// strong reference then the event 
  59:          /// handler will be gc’ed.
  60:          /// </summary>
  61:          private EventHandler CanExecuteChangedHandler;
  62:   
  63:   
  64:   
  65:          private void OnCommandChanged(ICommand oldCommand, 
  66:              ICommand newCommand)
  67:          {
  68:              if (oldCommand != null)
  69:                  UnhookCommand(oldCommand);
  70:              if (newCommand != null)
  71:                  HookCommand(newCommand);
  72:          }
  73:   
  74:          private void UnhookCommand(ICommand command)
  75:          {
  76:              command.CanExecuteChanged -= 
  77:                  CanExecuteChangedHandler;
  78:              UpdateCanExecute();
  79:          }
  80:   
  81:          private void HookCommand(ICommand command)
  82:          {
  83:              // Save a strong reference to the 
  84:              // Command.CanExecuteChanged event handler. 
  85:              // The commanding system uses a weak 
  86:              // reference and if we don’t save a strong 
  87:              // reference then the event handler will be gc’ed.
  88:              CanExecuteChangedHandler = 
  89:                  new EventHandler(OnCanExecuteChanged);
  90:              command.CanExecuteChanged 
  91:                  += CanExecuteChangedHandler;
  92:              UpdateCanExecute();
  93:          }
  94:   
  95:          private void OnCanExecuteChanged(object sender, 
  96:              EventArgs e)
  97:          {
  98:              UpdateCanExecute();
  99:          }
 100:   
 101:          private void UpdateCanExecute()
 102:          {
 103:              if (Command != null)
 104:              {
 105:                  RoutedCommand command = 
 106:                       Command as RoutedCommand;
 107:                  if (command != null)
 108:                      IsEnabled = 
 109:                          command.CanExecute(
 110:                           CommandParameter, CommandTarget);
 111:                  else
 112:                      IsEnabled = 
 113:                          Command.CanExecute(CommandParameter);
 114:                  if (Target != null && SyncOwnerIsEnabled)
 115:                      Target.IsEnabled = IsEnabled;
 116:              }
 117:          }
 118:   
 119:          #endregion
 120:   
 121:   
 122:          #endregion
 123:   
 124:          #region CommandParameter DP
 125:          /// <summary>
 126:          /// For consistency with the Wpf Command pattern
 127:          /// </summary>
 128:          [Category("Command Properties")]
 129:          public object CommandParameter
 130:          {
 131:              get { return (object)GetValue(
 132:                  CommandParameterProperty); }
 133:              set { SetValue(CommandParameterProperty, value); }
 134:          }
 135:   
 136:          public static readonly DependencyProperty 
 137:              CommandParameterProperty =
 138:              DependencyProperty.Register(
 139:                  "CommandParameter", typeof(object), 
 140:                      typeof(InteractionsSelectorDoubleClickCommandAction),
 141:                          new PropertyMetadata());
 142:          #endregion
 143:   
 144:          #region CommandTarget DP
 145:          /// <summary>
 146:          /// For consistency with the Wpf Command pattern
 147:          /// </summary>
 148:          [Category("Command Properties")]
 149:          public IInputElement CommandTarget
 150:          {
 151:              get { return (IInputElement)GetValue(
 152:                  CommandTargetProperty); }
 153:              set { SetValue(CommandTargetProperty, value); }
 154:          }
 155:   
 156:          public static readonly DependencyProperty 
 157:              CommandTargetProperty =
 158:              DependencyProperty.Register(
 159:                  "CommandTarget", typeof(IInputElement), 
 160:                      typeof(InteractionsSelectorDoubleClickCommandAction),
 161:                          new PropertyMetadata());
 162:          #endregion
 163:   
 164:          #region SyncOwnerIsEnabled DP
 165:          /// <summary>
 166:          /// Allows the user to specify that the 
 167:          /// owner element should be 
 168:          /// enabled/disabled whenever the 
 169:          /// action is enabled/disabled.
 170:          /// </summary>
 171:          [Category("Command Properties")]
 172:          public bool SyncOwnerIsEnabled
 173:          {
 174:              get { return (bool)GetValue(SyncOwnerIsEnabledProperty); }
 175:              set { SetValue(SyncOwnerIsEnabledProperty, value); }
 176:          }
 177:   
 178:          /// <summary>
 179:          /// When SyncOwnerIsEnabled is true 
 180:          /// then changing 
 181:          /// InteractionsSelectorDoubleClickCommandAction.
 182:          /// IsEnabled 
 183:          /// will automatically update the owner 
 184:          /// (Target) IsEnabled property.
 185:          /// </summary>
 186:          public static readonly DependencyProperty 
 187:              SyncOwnerIsEnabledProperty =
 188:              DependencyProperty.Register(
 189:                  "SyncOwnerIsEnabled", typeof(bool), 
 190:                      typeof(InteractionsSelectorDoubleClickCommandAction),
 191:                      new PropertyMetadata());
 192:          #endregion
 193:   
 194:          #endregion
 195:   
 196:          #region Overrides
 197:          /// <summary>
 198:          /// On attached hook up our own MouseDoubleClick so we
 199:          /// can check we actually double click an item
 200:          /// </summary>
 201:          protected override void OnAttached()
 202:          {
 203:              base.OnAttached();
 204:              Selector s = this.AssociatedObject as Selector;
 205:              if (s != null)
 206:              {
 207:                  s.MouseDoubleClick += OnMouseDoubleClick;
 208:              }
 209:          }
 210:   
 211:          /// <summary>
 212:          /// On attached unhook the previously 
 213:          /// hooked MouseDoubleClick handler
 214:          /// </summary>
 215:          protected override void OnDetaching()
 216:          {
 217:              base.OnDetaching();
 218:              Selector s = this.AssociatedObject as Selector;
 219:              if (s != null)
 220:              {
 221:                  s.MouseDoubleClick -= OnMouseDoubleClick;
 222:              }
 223:          }
 224:   
 225:          //Must at least implement abstract member invoke
 226:          protected override void Invoke(object parameter)
 227:          {
 228:              //The logic for this is done in the OnMouseDoubleClick
 229:              //as we only wanto fire command if we are actually on an
 230:              //Item in the Selector. If the Selector is a ListView we
 231:              //may have headers so will not want to fire associated
 232:              //Command when a header is double clicked
 233:          }
 234:          #endregion
 235:   
 236:          #region Private Methods
 237:   
 238:          /// <summary>
 239:          /// Handle Selector.MouseDoubleClick but will 
 240:          /// only fire the associated ViewModel command 
 241:          /// if the MouseDoubleClick occurred over an actual
 242:          /// ItemsControl item. This is nessecary as if we 
 243:          /// are using a ListView we may have clicked the 
 244:          /// headers which are not items, so do not want the
 245:          /// associated ViewModel command to be run
 246:          /// </summary>
 247:          private static void OnMouseDoubleClick(object sender,
 248:              MouseButtonEventArgs e)
 249:          {
 250:              //Get the ItemsControl and then get the item, and 
 251:              //check there is an actual item, as if we are using 
 252:              //a ListView we may have clicked the
 253:              //headers which are not items
 254:              ItemsControl listView = sender as ItemsControl;
 255:              DependencyObject originalSender =
 256:                  e.OriginalSource as DependencyObject;
 257:              if (listView == null || originalSender == null) return;
 258:   
 259:              DependencyObject container =
 260:                  ItemsControl.ContainerFromElement
 261:                  (sender as ItemsControl,
 262:                  e.OriginalSource as DependencyObject);
 263:   
 264:              if (container == null ||
 265:                  container == DependencyProperty.UnsetValue) return;
 266:   
 267:              // found a container, now find the item.
 268:              object activatedItem =
 269:                  listView.ItemContainerGenerator.
 270:                      ItemFromContainer(container);
 271:   
 272:              if (activatedItem != null)
 273:              {
 274:                  ICommand command =
 275:                      (ICommand)(sender as DependencyObject).
 276:                      GetValue(TheCommandToRunProperty);
 277:   
 278:                  if (command != null)
 279:                  {
 280:                      if (command.CanExecute(null))
 281:                          command.Execute(null);
 282:                  }
 283:              }
 284:          }
 285:   
 286:          #endregion
 287:      }
 288:   
 289:  }

Which we could use from XAML as follows:

   1:  <Window x:Class="ListViewDoubleCLick.Window1"
   2:      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:      xmlns:local="clr-namespace:ListViewDoubleCLick"
   5:      xmlns:interactivity="clr-namespace:Microsoft.Expression.Interactivity;
                                assembly=Microsoft.Expression.Interactivity" 
   6:      Title="Window1" Height="600" Width="800" 
   7:      WindowStartupLocation="CenterScreen">
   8:      <Grid>
   9:   
  10:          <TabControl>
  11:               <TabItem Header="Using Blend3 Interactivity Dll" >
  12:                  <ListView ItemsSource="{Binding People}" 
  13:                    IsSynchronizedWithCurrentItem="True">
  14:   
  15:                      <interactivity:Interaction.Triggers>
  16:                          <interactivity:EventTrigger EventName="MouseDoubleClick">
  17:                              <local:InteractionsSelectorDoubleClickCommandAction 
  18:                                  Command="{Binding DoItCommand}" 
  19:                                  SyncOwnerIsEnabled="True" />
  20:                          </interactivity:EventTrigger>
  21:                      </interactivity:Interaction.Triggers>
  22:   
  23:                      <ListView.View>
  24:                          <GridView>
  25:                              <GridViewColumn Header="FirstName"
  26:                                      DisplayMemberBinding="{Binding FirstName}"
  27:                                      Width="80" />
  28:                              <GridViewColumn Header="LastName" 
  29:                                      DisplayMemberBinding="{Binding LastName}"  
  30:                                      Width="80"/>
  31:                          </GridView>
  32:                      </ListView.View>
  33:                  </ListView>
  34:              </TabItem>
  35:          </TabControl>
  36:          
  37:   
  38:   
  39:      </Grid>
  40:   
  41:  </Window>

As usual, here is a small demo project:

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Sacha Barber
Software Developer (Senior)
United Kingdom United Kingdom
Member
I currently hold the following qualifications (amongst others, I also studied Music Technology and Electronics, for my sins)
 
- MSc (Passed with distinctions), in Information Technology for E-Commerce
- BSc Hons (1st class) in Computer Science & Artificial Intelligence
 
Both of these at Sussex University UK.
 
Award(s)

I am lucky enough to have won a few awards for Zany Crazy code articles over the years

  • Microsoft C# MVP 2013
  • Codeproject MVP 2013
  • Microsoft C# MVP 2012
  • Codeproject MVP 2012
  • Microsoft C# MVP 2011
  • Codeproject MVP 2011
  • Microsoft C# MVP 2010
  • Codeproject MVP 2010
  • Microsoft C# MVP 2009
  • Codeproject MVP 2009
  • Microsoft C# MVP 2008
  • Codeproject MVP 2008
  • And numerous codeproject awards which you can see over at my blog

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralArticlememberzdebyman25 Oct '12 - 2:09 
Thanks!
Awersome article!
QuestionWhat do you mean by 'DoItCommand'?memberBob Brady12 Sep '12 - 10:24 
Excellent code and very informative, but while I can capture the Double Click, I can't get it to do whatever DoItCommand does.
 
By the way, the associated code leads to an invalid link
 
I tried a simple public void DoItCommand() in the ViewModel and it didn't result in anything
AnswerRe: What do you mean by 'DoItCommand'?mvpSacha Barber12 Sep '12 - 19:27 
The "DoItCommand" is a binding that should be bound to a ICommand in your vm,see the xaml here again, it shows example.
 
Link is bad cos I had to change blogs.
Sacha Barber
  • Microsoft Visual C# MVP 2008-2012
  • Codeproject MVP 2008-2012
Open Source Projects
Cinch SL/WPF MVVM

Your best friend is you.
I'm my best friend too. We share the same views, and hardly ever argue
 
My Blog : sachabarber.net

AnswerRe: What do you mean by 'DoItCommand'?mvpSacha Barber12 Sep '12 - 19:30 
Also see comments in this file http://cinch.codeplex.com/SourceControl/changeset/view/68724#782975[^]
 
You just need ICommand (some sort of delegate based ICommand in your vm, grab one from my cinch mvvm framework if you don't have one)
Sacha Barber
  • Microsoft Visual C# MVP 2008-2012
  • Codeproject MVP 2008-2012
Open Source Projects
Cinch SL/WPF MVVM

Your best friend is you.
I'm my best friend too. We share the same views, and hardly ever argue
 
My Blog : sachabarber.net

GeneralRe: What do you mean by 'DoItCommand'?memberBob Brady13 Sep '12 - 4:12 
I think my problems are deriving from your use of the Microsoft.Expressions.Interactivity.dll, which I couldn't successfully extract from the Blend3 download. Whenever I get to the RunTheCommand function, it returns a null command and the whole thing fails.
 
I can see from search for help on this that this is a common problem with the .dll (I guess it's easy to get the wrong version of that .dll on your PC and hard to correct it). However, even when I reference the .dll manually, I can't access the .Interactivity dll, just the Blend3SDK or Interactions, neither of which help me.
 
I also tried to replace with the Windows.System.Interactivity.dll and write my own RunTheCommand, using references I was able to find, but that didn't work, either.
 
However, I appreciate that you put continuing effort into supporting and explaining this. It WOULD be easier with a valid example, I think.
 
You're obviously an excellent programmer and it speaks to your character that you do this out of the goodness of your hear
QuestionMicrosoft.Expression.Interactivitymemberbrettles2 Sep '12 - 21:46 
Hi Sacha,
 
Thanks for your great post.
I am implementing the Interactivity model now and i am wondering in the second code snippit you still reference TheCommandToRunProperty even though it does not exist.
When I try to grab the CommandProperty it is null, do you know what object i am chasing here? (Line 276)
 
272: if (activatedItem != null)
273: {
274: ICommand command =
275: (ICommand)(sender as DependencyObject).
276: GetValue(TheCommandToRunProperty);
277:
278: if (command != null)
279: {
280: if (command.CanExecute(null))
281: command.Execute(null);
282: }  
Cheers.
BugPotential Memory LeakmemberClifford Nelson7 Jun '12 - 8:18 
From what I understand, you really need to add a removal of the event handler in the OnHandleDoubleClickChanged when you get a false.
GeneralRe: Potential Memory LeakmvpSacha Barber7 Jun '12 - 9:33 
When would it get to false. Far better to use weak events see my cinch mvvm framework for example of that
Sacha Barber
  • Microsoft Visual C# MVP 2008-2012
  • Codeproject MVP 2008-2012
Open Source Projects
Cinch SL/WPF MVVM

Your best friend is you.
I'm my best friend too. We share the same views, and hardly ever argue
 
My Blog : sachabarber.net

QuestionImplemented in Cinch?memberaaj2318 Apr '12 - 3:01 
Hey Sacha,
Per usual your code is excellent and extremely helpful (thank you). Is this something you've implemented or plan to implement in Cinch v2? I use Cinch now and will implement this class in the interim, but if it's already there I'd hate to be duplicating code.
Thanks!
Aj
AnswerRe: Implemented in Cinch?mvpSacha Barber18 Apr '12 - 3:09 
Yeah it is already part of CInch
 
Cinch V1 uses attached property : http://cinch.codeplex.com/SourceControl/changeset/view/68724#782975
 
Cinch V2 uses Blend interactivity Dll (Behaviours/Triggers etc etc) : http://cinch.codeplex.com/SourceControl/changeset/view/68724#796996
 

I did not make it available in the SL version of Cinch V2, but I think you could port the code fairly easily if you wanted to use it in SL
Sacha Barber
  • Microsoft Visual C# MVP 2008-2012
  • Codeproject MVP 2008-2012
Open Source Projects
Cinch SL/WPF MVVM

Your best friend is you.
I'm my best friend too. We share the same views, and hardly ever argue
 
My Blog : sachabarber.net

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 8 Sep 2009
Article Copyright 2009 by Sacha Barber
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid