WPF CommandParameter is NULL first time CanExecute is called
Asked Answered
J

16

99

I have run into an issue with WPF and Commands that are bound to a Button inside the DataTemplate of an ItemsControl. The scenario is quite straight forward. The ItemsControl is bound to a list of objects, and I want to be able to remove each object in the list by clicking a Button. The Button executes a Command, and the Command takes care of the deletion. The CommandParameter is bound to the Object I want to delete. That way I know what the user clicked. A user should only be able to delete their "own" objects - so I need to do some checks in the "CanExecute" call of the Command to verify that the user has the right permissions.

The problem is that the parameter passed to CanExecute is NULL the first time it's called - so I can't run the logic to enable/disable the command. However, if I make it allways enabled, and then click the button to execute the command, the CommandParameter is passed in correctly. So that means that the binding against the CommandParameter is working.

The XAML for the ItemsControl and the DataTemplate looks like this:

<ItemsControl 
    x:Name="commentsList"
    ItemsSource="{Binding Path=SharedDataItemPM.Comments}"
    Width="Auto" Height="Auto">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <Button                             
                    Content="Delete"
                    FontSize="10"
                    Command="{Binding Path=DataContext.DeleteCommentCommand, ElementName=commentsList}" 
                    CommandParameter="{Binding}" />
            </StackPanel>                       
         </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

So as you can see I have a list of Comments objects. I want the CommandParameter of the DeleteCommentCommand to be bound to the Command object.

So I guess my question is: have anyone experienced this problem before? CanExecute gets called on my Command, but the parameter is always NULL the first time - why is that?

Update: I was able to narrow the problem down a little. I added an empty Debug ValueConverter so that I could output a message when the CommandParameter is data bound. Turns out the problem is that the CanExecute method is executed before the CommandParameter is bound to the button. I have tried to set the CommandParameter before the Command (like suggested) - but it still doesn't work. Any tips on how to control it.

Update2: Is there any way to detect when the binding is "done", so that I can force re-evaluation of the command? Also - is it a problem that I have multiple Buttons (one for each item in the ItemsControl) that bind to the same instance of a Command-object?

Update3: I have uploaded a reproduction of the bug to my SkyDrive: http://cid-1a08c11c407c0d8e.skydrive.live.com/self.aspx/Code%20samples/CommandParameterBinding.zip

Jaundiced answered 2/12, 2008 at 23:49 Comment(2)
I have exact same problem, with a ListBox.Rodrickrodrigez
There is a currently open bug report against WPF for this issue: github.com/dotnet/wpf/issues/316Baseball
D
18

I stumbled upon a similar problem and solved it using my trusty TriggerConverter.

public class TriggerConverter : IMultiValueConverter
{
    #region IMultiValueConverter Members

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        // First value is target value.
        // All others are update triggers only.
        if (values.Length < 1) return Binding.DoNothing;
        return values[0];
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    #endregion
}

This value converter takes any number of parameters and passes the first of them back as the converted value. When used in a MultiBinding in your case it looks like the following.

<ItemsControl 
    x:Name="commentsList"
    ItemsSource="{Binding Path=SharedDataItemPM.Comments}"
    Width="Auto" Height="Auto">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <Button                             
                    Content="Delete"
                    FontSize="10"
                    CommandParameter="{Binding}">
                    <Button.Command>
                        <MultiBinding Converter="{StaticResource TriggerConverter}">
                            <Binding Path="DataContext.DeleteCommentCommand"
                                     ElementName="commentsList" />
                            <Binding />
                        </MultiBinding> 
                    </Button.Command>
                </Button>
            </StackPanel>                                       
         </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

You will have to add TriggerConverter as a resource somewhere for this to work. Now the Command property is set not before the value for the CommandParameter has become available. You could even bind to RelativeSource.Self and CommandParameter instead of . to achieve the same effect.

Diversion answered 5/2, 2009 at 16:22 Comment(4)
This worked for me. I do not understand why. Can anyone explain?How
Doesnt it work cause the CommandParameter is bound before the Command? I doubt you would need the converter...Shiekh
This is not a solution. This is a hack? What the hell is going on? This used to work?Ecclesiastical
Perfect, works for me! The magic is in the <Binding /> line, which causes the command binding to get updated when the data template changes (which is bound to the command parameter)Montemayor
B
67

I was having this same issue while trying to bind to a command on my view model.

I changed it to use a relative source binding rather than referring to the element by name and that did the trick. Parameter binding didn't change.

Old Code:

Command="{Binding DataContext.MyCommand, ElementName=myWindow}"

New Code:

Command="{Binding DataContext.MyCommand, RelativeSource={RelativeSource AncestorType=Views:MyView}}"

Update: I just came across this issue without using ElementName, I'm binding to a command on my view model and my data context of the button is my view model. In this case I had to simply move the CommandParameter attribute before the Command attribute in the Button declaration (in XAML).

CommandParameter="{Binding Groups}"
Command="{Binding StartCommand}"
Barilla answered 28/10, 2010 at 21:39 Comment(9)
Moving the CommandParameter in front of the Command is the best answer on this thread.Kalbli
Moving the order of the attributes did not help us. I would be surprised if it had an effect on the order of execution.Wolfgram
I don't know why this works. It feels like it shouldn't but it totally does.Ekg
The RelativeSource solution worked great for me, and didn't require an unnecessary converter. RelativeSource "feels" better too, as it isn't arbitrarily coupled to a text string. It's looking up the tree to the element above it that has the value it needs.Alost
I had the same problem - RelativeSource didn't help, changing the order of the attributes did. Thanks for the update!Inculpable
As a person who religiously uses extensions to automatically beautify XAML (split attributes across lines, fix indentation, reorder attributes) the proposal of changing the order of CommandParameter and Command scares me.Allieallied
Perfect! Worked for me. Many thanks! (I'm using Prism and DelegeteCommand<T>)Unwell
@JackUkleja Of course, the sequence of the attributes matters: guess in what sequence the dependency properties get initialized...Nicolas
I had this same problem when the ElementName was not unique (due to copy/paste). Changing to RelativeSource or renaming the element solved the issue.Algicide
M
35

I have found that the order in which I set Command and CommandParameter makes a difference. Setting the Command property causes CanExecute to be called immediately, so you want CommandParameter to already be set at that point.

I have found that switching the order of the properties in the XAML can actually have an effect, though I'm not confident that it will solve your problem. It's worth a try, though.

You seem to be suggesting that the button never becomes enabled, which is surprising, since I would expect the CommandParameter to be set shortly after the Command property in your example. Does calling CommandManager.InvalidateRequerySuggested() cause the button to become enabled?

Marten answered 3/12, 2008 at 4:59 Comment(2)
Tried setting the CommandParameter before the Command - still executes CanExecute, but still passing in NULL... Bummer - but thanks for the tip. Also, calling CommandManager.InvalidateRequerySuggested(); does not make any difference.Baeyer
CommandManager.InvalidateRequerySuggested() solved a similar issue for me. Thanks!Betrothal
P
19

I've come up with another option to work around this issue that I wanted to share. Because the CanExecute method of the command gets executed before the CommandParameter property is set, I created a helper class with an attached property that forces the CanExecute method to be called again when the binding changes.

public static class ButtonHelper
{
    public static DependencyProperty CommandParameterProperty = DependencyProperty.RegisterAttached(
        "CommandParameter",
        typeof(object),
        typeof(ButtonHelper),
        new PropertyMetadata(CommandParameter_Changed));

    private static void CommandParameter_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var target = d as ButtonBase;
        if (target == null)
            return;

        target.CommandParameter = e.NewValue;
        var temp = target.Command;
        // Have to set it to null first or CanExecute won't be called.
        target.Command = null;
        target.Command = temp;
    }

    public static object GetCommandParameter(ButtonBase target)
    {
        return target.GetValue(CommandParameterProperty);
    }

    public static void SetCommandParameter(ButtonBase target, object value)
    {
        target.SetValue(CommandParameterProperty, value);
    }
}

And then on the button you want to bind a command parameter to...

<Button 
    Content="Press Me"
    Command="{Binding}" 
    helpers:ButtonHelper.CommandParameter="{Binding MyParameter}" />

I hope this perhaps helps someone else with the issue.

Pigweed answered 10/7, 2014 at 6:16 Comment(2)
Nicely done, thank you. I can't believe M$ hasn't fixed this after 8 years. Turrible!Howard
This solution worked in my case, however I ended up going with Simon Smith's solution because it is simpler (only requires a binding format change in the XAML)Obsession
D
18

I stumbled upon a similar problem and solved it using my trusty TriggerConverter.

public class TriggerConverter : IMultiValueConverter
{
    #region IMultiValueConverter Members

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        // First value is target value.
        // All others are update triggers only.
        if (values.Length < 1) return Binding.DoNothing;
        return values[0];
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    #endregion
}

This value converter takes any number of parameters and passes the first of them back as the converted value. When used in a MultiBinding in your case it looks like the following.

<ItemsControl 
    x:Name="commentsList"
    ItemsSource="{Binding Path=SharedDataItemPM.Comments}"
    Width="Auto" Height="Auto">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <Button                             
                    Content="Delete"
                    FontSize="10"
                    CommandParameter="{Binding}">
                    <Button.Command>
                        <MultiBinding Converter="{StaticResource TriggerConverter}">
                            <Binding Path="DataContext.DeleteCommentCommand"
                                     ElementName="commentsList" />
                            <Binding />
                        </MultiBinding> 
                    </Button.Command>
                </Button>
            </StackPanel>                                       
         </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

You will have to add TriggerConverter as a resource somewhere for this to work. Now the Command property is set not before the value for the CommandParameter has become available. You could even bind to RelativeSource.Self and CommandParameter instead of . to achieve the same effect.

Diversion answered 5/2, 2009 at 16:22 Comment(4)
This worked for me. I do not understand why. Can anyone explain?How
Doesnt it work cause the CommandParameter is bound before the Command? I doubt you would need the converter...Shiekh
This is not a solution. This is a hack? What the hell is going on? This used to work?Ecclesiastical
Perfect, works for me! The magic is in the <Binding /> line, which causes the command binding to get updated when the data template changes (which is bound to the command parameter)Montemayor
L
14

I'll add what worked for me for a DataGridTemplateColumn with a button.

Change the binding from:

CommandParameter="{Binding .}"

to

CommandParameter="{Binding DataContext, RelativeSource={RelativeSource Self}}"

Not sure why it works, but it did for me.

Lodi answered 15/8, 2016 at 18:46 Comment(2)
I have tried both high score answers above, but this one only worked for me. It seems it is internal problem of control itself not the binding, but still many people got it working with above answers. Thanks!Idle
This worked perfectly for my case and is the cleanest solution I see here (way cleaner than changing the order of Command and CommandParameter, which didn't work for me anyways)Obsession
D
8

I recently came across the same problem (for me it was for the menu items in a context menu), nad while it may not be a suitable solution for every situation, I found a different (and a lot shorter!) way of solving this problem:

<MenuItem Header="Open file" Command="{Binding Tag.CommandOpenFile, IsAsync=True, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}" CommandParameter="{Binding Name}" />

Ignoring the Tag-based workaround for the special case of context menu, the key here is to bind the CommandParameter regularly, but bind the Command with the additional IsAsync=True. This will delay the binding of the actual command (and therefore its CanExecute call) a bit, so the parameter will already be available. This means, though, that for a brief moment, the enabled-state might be wrong, but for my case, that was perfectly acceptable.

Domoniquedomph answered 10/5, 2019 at 12:37 Comment(0)
S
5

You may be able to use my CommandParameterBehavior that I posted to the Prism forums yesterday. It adds the missing behaviour where a change to the CommandParameter cause the Command to be re-queried.

There's some complexity here caused by my attempts to avoid the memory leak caused if you call PropertyDescriptor.AddValueChanged without later calling PropertyDescriptor.RemoveValueChanged. I try and fix that by unregistering the handler when the ekement is unloaded.

You'll probably need to remove the IDelegateCommand stuff unless you're using Prism (and want to make the same changes as me to the Prism library). Also note that we don't generally use RoutedCommands here (we use Prism's DelegateCommand<T> for pretty much everything) so please don't hold me responsible if my call to CommandManager.InvalidateRequerySuggested sets off some sort of quantum wavefuntion collapse cascade that destroys the known universe or anything.

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;

namespace Microsoft.Practices.Composite.Wpf.Commands
{
    /// <summary>
    /// This class provides an attached property that, when set to true, will cause changes to the element's CommandParameter to 
    /// trigger the CanExecute handler to be called on the Command.
    /// </summary>
    public static class CommandParameterBehavior
    {
        /// <summary>
        /// Identifies the IsCommandRequeriedOnChange attached property
        /// </summary>
        /// <remarks>
        /// When a control has the <see cref="IsCommandRequeriedOnChangeProperty" />
        /// attached property set to true, then any change to it's 
        /// <see cref="System.Windows.Controls.Primitives.ButtonBase.CommandParameter" /> property will cause the state of
        /// the command attached to it's <see cref="System.Windows.Controls.Primitives.ButtonBase.Command" /> property to 
        /// be reevaluated.
        /// </remarks>
        public static readonly DependencyProperty IsCommandRequeriedOnChangeProperty =
            DependencyProperty.RegisterAttached("IsCommandRequeriedOnChange",
                                                typeof(bool),
                                                typeof(CommandParameterBehavior),
                                                new UIPropertyMetadata(false, new PropertyChangedCallback(OnIsCommandRequeriedOnChangeChanged)));

        /// <summary>
        /// Gets the value for the <see cref="IsCommandRequeriedOnChangeProperty"/> attached property.
        /// </summary>
        /// <param name="target">The object to adapt.</param>
        /// <returns>Whether the update on change behavior is enabled.</returns>
        public static bool GetIsCommandRequeriedOnChange(DependencyObject target)
        {
            return (bool)target.GetValue(IsCommandRequeriedOnChangeProperty);
        }

        /// <summary>
        /// Sets the <see cref="IsCommandRequeriedOnChangeProperty"/> attached property.
        /// </summary>
        /// <param name="target">The object to adapt. This is typically a <see cref="System.Windows.Controls.Primitives.ButtonBase" />, 
        /// <see cref="System.Windows.Controls.MenuItem" /> or <see cref="System.Windows.Documents.Hyperlink" /></param>
        /// <param name="value">Whether the update behaviour should be enabled.</param>
        public static void SetIsCommandRequeriedOnChange(DependencyObject target, bool value)
        {
            target.SetValue(IsCommandRequeriedOnChangeProperty, value);
        }

        private static void OnIsCommandRequeriedOnChangeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (!(d is ICommandSource))
                return;

            if (!(d is FrameworkElement || d is FrameworkContentElement))
                return;

            if ((bool)e.NewValue)
            {
                HookCommandParameterChanged(d);
            }
            else
            {
                UnhookCommandParameterChanged(d);
            }

            UpdateCommandState(d);
        }

        private static PropertyDescriptor GetCommandParameterPropertyDescriptor(object source)
        {
            return TypeDescriptor.GetProperties(source.GetType())["CommandParameter"];
        }

        private static void HookCommandParameterChanged(object source)
        {
            var propertyDescriptor = GetCommandParameterPropertyDescriptor(source);
            propertyDescriptor.AddValueChanged(source, OnCommandParameterChanged);

            // N.B. Using PropertyDescriptor.AddValueChanged will cause "source" to never be garbage collected,
            // so we need to hook the Unloaded event and call RemoveValueChanged there.
            HookUnloaded(source);
        }

        private static void UnhookCommandParameterChanged(object source)
        {
            var propertyDescriptor = GetCommandParameterPropertyDescriptor(source);
            propertyDescriptor.RemoveValueChanged(source, OnCommandParameterChanged);

            UnhookUnloaded(source);
        }

        private static void HookUnloaded(object source)
        {
            var fe = source as FrameworkElement;
            if (fe != null)
            {
                fe.Unloaded += OnUnloaded;
            }

            var fce = source as FrameworkContentElement;
            if (fce != null)
            {
                fce.Unloaded += OnUnloaded;
            }
        }

        private static void UnhookUnloaded(object source)
        {
            var fe = source as FrameworkElement;
            if (fe != null)
            {
                fe.Unloaded -= OnUnloaded;
            }

            var fce = source as FrameworkContentElement;
            if (fce != null)
            {
                fce.Unloaded -= OnUnloaded;
            }
        }

        static void OnUnloaded(object sender, RoutedEventArgs e)
        {
            UnhookCommandParameterChanged(sender);
        }

        static void OnCommandParameterChanged(object sender, EventArgs ea)
        {
            UpdateCommandState(sender);
        }

        private static void UpdateCommandState(object target)
        {
            var commandSource = target as ICommandSource;

            if (commandSource == null)
                return;

            var rc = commandSource.Command as RoutedCommand;
            if (rc != null)
            {
                CommandManager.InvalidateRequerySuggested();
            }

            var dc = commandSource.Command as IDelegateCommand;
            if (dc != null)
            {
                dc.RaiseCanExecuteChanged();
            }

        }
    }
}
Syllabism answered 18/2, 2009 at 15:34 Comment(2)
came across your bug report at connect. Any chance you could update your post here with your last code of this? or have you since found a better work around?Oralle
An easier solution may be to observe the CommandParameter property using a binding instead of a property descriptor. Otherwise a great solution! This one actually fixes the underlying issue instead of just introducing an awkward hack or workaround.Urethra
D
1

There's a relatively simple way to "fix" this problem with DelegateCommand, though it requires updating the DelegateCommand source and re-compiling the Microsoft.Practices.Composite.Presentation.dll.

1) Download the Prism 1.2 source code and open the CompositeApplicationLibrary_Desktop.sln. In here is a Composite.Presentation.Desktop project that contains the DelegateCommand source.

2) Under the public event EventHandler CanExecuteChanged, modify to read as follows:

public event EventHandler CanExecuteChanged
{
     add
     {
          WeakEventHandlerManager.AddWeakReferenceHandler( ref _canExecuteChangedHandlers, value, 2 );
          // add this line
          CommandManager.RequerySuggested += value;
     }
     remove
     {
          WeakEventHandlerManager.RemoveWeakReferenceHandler( _canExecuteChangedHandlers, value );
          // add this line
          CommandManager.RequerySuggested -= value;
     }
}

3) Under protected virtual void OnCanExecuteChanged(), modify it as follows:

protected virtual void OnCanExecuteChanged()
{
     // add this line
     CommandManager.InvalidateRequerySuggested();
     WeakEventHandlerManager.CallWeakReferenceHandlers( this, _canExecuteChangedHandlers );
}

4) Recompile the solution, then navigate to either the Debug or Release folder where the compiled DLLs live. Copy the Microsoft.Practices.Composite.Presentation.dll and .pdb (if you wish) to where you references your external assemblies, and then recompile your application to pull the new versions.

After this, CanExecute should be fired every time the UI renders elements bound to the DelegateCommand in question.

Take care, Joe

refereejoe at gmail

Donielle answered 8/4, 2010 at 18:1 Comment(0)
A
1

After reading some good answers to similar questions I changed in your example the DelegateCommand slightly to make it work. Instead of using:

public event EventHandler CanExecuteChanged;

I changed it to:

public event EventHandler CanExecuteChanged
{
    add { CommandManager.RequerySuggested += value; }
    remove { CommandManager.RequerySuggested -= value; }
}

I removed the following two methods because I was too lazy to fix them

public void RaiseCanExecuteChanged()

and

protected virtual void OnCanExecuteChanged()

And that's all... this seems to ensure that CanExecute will be called when the Binding changes and after the Execute method

It will not automatically trigger if the ViewModel is changed but as mentioned in this thread possible by calling the CommandManager.InvalidateRequerySuggested on the GUI thread

Application.Current?.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)CommandManager.InvalidateRequerySuggested);
Androecium answered 29/11, 2015 at 10:41 Comment(1)
I have found that DispatcherPriority.Normal is too high to work reliably (or at all, in my case). Using DispatcherPriority.Loaded works well, and seems more appropriate (i.e. is explicitly indicating that the delegate isn't to be invoked until the UI elements associated with the view model have in fact been loaded).Amundsen
B
1

In .NET 7.0 RC1 this has been fixed.

(At least in a sense...)

It should now automatically reevaluate CanExecute() whenever CommandParameter changes, including upon initialization.

Although that does not prevent the initial call to CanExecute() when CommandParameter is still null, many ICommand implementations should already be handling that and it does render obsolete the obscure and problematic XAML attribute ordering workaround / hack.

As intimated by @Daniel-Svensson in a GitHub comment:

the actual issue here is that ICommand.CanExecute is not reevaluated when the value bound to CommandParameter changes. Doing so would obviously be the correct behavior, since the command parameter is passed to CanExecute, so everyone expects this behavior intuitively.

And that is what is being fixed.


According to @pchaurasia14, a Sr. Engineering Manager for WPF at Microsoft:

This has been fixed in RC1 release. You may try it out. ... I meant, .NET 7 RC1.

The GitHub tracking issue #316 in the dotnet/wpf project is listed as closed. The code change CommandParameter invalidates CanExecute #4217 has been included in .NET 7.0 RC1. It was merged on July 21, 2022 and is included in the list of commits (scroll way down) for the RC1 release.

Baseball answered 9/9, 2022 at 21:34 Comment(0)
N
0

not sure if this will work in a data template, but here is the binding syntax I use in a ListView Context menu to grab the current item as a command parameter:

CommandParameter=
          "{Binding RelativeSource={RelativeSource AncestorType=ContextMenu},
                    Path=PlacementTarget.SelectedItem,
                    Mode=TwoWay}"
Nonce answered 4/12, 2008 at 14:26 Comment(1)
I do the exact same thing in my list view. In this case it is a ItemsControl so there is no obvious property to "bind up" against (in the visual tree). I guess I have to find a way to detect when binding is done, and re-evaluate CanExecute (because CommandParameter gets bound, just to late)Baeyer
S
0

I've logged this as a bug against WPF in .Net 4.0, as the problem still exists in Beta 2.

https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=504976

Syllabism answered 26/11, 2009 at 14:18 Comment(1)
feedback link is no longer validAmundsen
H
0

Some of these answers are about binding to the DataContext to get the Command itself, but the question was about the CommandParameter being null when it shouldn't be. We also experienced this. On on a hunch, we found a very simple way to get this to work in our ViewModel. This is specifically for the CommandParameter null problem reported by the customer, with one line of code. Note the Dispatcher.BeginInvoke().

public DelegateCommand<objectToBePassed> CommandShowReport
    {
        get
        {
            // create the command, or pass what is already created.
            var command = _commandShowReport ?? (_commandShowReport = new DelegateCommand<object>(OnCommandShowReport, OnCanCommandShowReport));

            // For the item template, the OnCanCommand will first pass in null. This will tell the command to re-pass the command param to validate if it can execute.
            Dispatcher.BeginInvoke((Action) delegate { command.RaiseCanExecuteChanged(); }, DispatcherPriority.DataBind);

            return command;
        }
    }
Hager answered 21/6, 2016 at 23:19 Comment(0)
F
-1

Its a long shot. to debug this you can try:
- checking the PreviewCanExecute event.
- use snoop/wpf mole to peek inside and see what the commandparameter is.

HTH,

Floorage answered 4/12, 2008 at 4:55 Comment(1)
Tried using Snoop - but it's really hard to debug as it's only NULL when it's initially loaded. If i run Snoop on it the Command and CommandParameter are both seth... It has to do with using Commands in DataTemplate.Baeyer
N
-1

The commandManager.InvalidateRequerySuggested works for me as well. I believe the following link talks about similar problem, and M$ dev confirmed the limitation in the current version, and the commandManager.InvalidateRequerySuggested is the workaround. http://social.expression.microsoft.com/Forums/en-US/wpf/thread/c45d2272-e8ba-4219-bb41-1e5eaed08a1f/

What important is the timing of invoking the commandManager.InvalidateRequerySuggested. This should be invoked after the relevant value change is notified.

Nonce answered 22/12, 2008 at 5:57 Comment(1)
that link is no longer validAmundsen
B
-2

Beside Ed Ball's suggestion on setting CommandParameter prior to Command, make sure your CanExecute method has a parameter of object type.

private bool OnDeleteSelectedItemsCanExecute(object SelectedItems)  
{
    // Your goes heres
}

Hope it prevents someone spending the huge amount of time I did to figure out how to receive SelectedItems as CanExecute parameter

Burnight answered 22/9, 2014 at 1:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.