1

I'm making my first steps into using Commands (by implementing the ICommand interface) in my Windows Phone applications. Now I've run into a problem I can't seem to figure out. I'm binding a control, in this case it's a textbox, to the CommandParameter property of a Button:

<Button x:Name="BTN_Search"
        Style="{StaticResource ButtonNoPressedStyle}"
        BorderThickness="0"
        ccontrols:TiltEffect.IsTiltEnabled="True"
        Grid.Column="1"
        Height="85"
        Margin="0,0,0,-2"
        CommandParameter="{Binding ElementName=TB_Search}"
        Command="{Binding SearchTermCommand}">
        <Button.Background>
            <ImageBrush ImageSource="/Assets/Images/searchbtn.png" />
        </Button.Background>
</Button>

When the application starts and the viewmodel is instantiated, the CanExecute method gets fired twice in a row.

public override bool CanExecute(object parameter)
    {
        if (parameter != null)
        {
            var textbox = parameter as TextBox;
            if ((textbox.DataContext as MainPageViewmodel).SearchTerm == null)
            {
                (textbox.DataContext as MainPageViewmodel).SearchTerm = "";
                return true;
            }
            else if (String.IsNullOrWhiteSpace(textbox.Text)) return false;
            else if (textbox.Text.Any(Char.IsDigit)) return false;
            else if (textbox.Text.Length < 4) return false;
            else if (_commandExecuting) return false;
            else
            {
                var bindingExpression = textbox.GetBindingExpression(TextBox.TextProperty);
                bindingExpression.UpdateSource();
                return true;
            }
        }
        return true;
    }

The first time the parameter is null and the second time it contains the textbox. Because of this behavior I have to make it so that these first two times, the CanExecute method returns true, else the button will be disabled.

I've read some other topics that it may have to do with RaiseCanExecuteChanged(), but I'm not so sure of that either. This question has some answers regarding this issue, but the answers don't fit my needs, since most solutions are for WPF (using the CommandManager, or a IMultiValueConverter) and others don't seem to work.

Is there any solution to make sure CanExecute only fires once, or what's the explanation for this behavior?

Community
  • 1
  • 1
Kaj
  • 333
  • 2
  • 8
  • It seems like an abuse of the ICommand pattern to update a binding expression inside the test for "CanExecute". Why would you need to do that? – McGarnagle May 16 '14 at 20:55
  • Because I had this idea of updating only when needed (when all requirements were met). After looking into this, I figured I could just add INotifyPropertyChanged to the property in question. Thank you for bringing this to my attention. But I'd still like to know why this is happening. – Kaj May 16 '14 at 21:19
  • I don't know why exactly, but this guess makes sense to me: the first check is when the command object is first constructed; and the second check is when the CommandParameter is bound (ie, the TB_Search element is loaded). – McGarnagle May 16 '14 at 21:33
  • So that means each control or property tied to the command, triggers RaiseCanExecuteChanged() when it has loaded or updated? – Kaj May 16 '14 at 21:41
  • Good questions, I really don't know ... I do from experience that property changes via NotifyPropertyChanged *do not* trigger it. Dependency property changes? Changes to the visual tree? No idea ... – McGarnagle May 16 '14 at 22:00
  • Hmmm, when I bind the SearchTerm property (a string) directly to the CommandParameter and I set this property in the constructor of my viewmodel, CanExecute also gets fired twice. First null and then with the value. It doesn't matter if I implement INotifyPropertyChanged though... am I missing something here? – Kaj May 17 '14 at 07:42

2 Answers2

0

I think your textbox is not initialized when command parameter is bounded first time. Try to bind textbox with viewmodel parameter (parameter must be DependencyProperty or your viewmodel must implement INotifyPropertyChanged interface) with twoway mode then pass this parameter to command parameter.

Mike
  • 3,766
  • 3
  • 18
  • 32
0

This answer doesn't provide any definite conclusions, but after I tested with various bindings on the CommandParameter and looking at the information provided by Microsoft for the ICommand interface and the associated CanExecuteChanged event, I have to conclude that it has to do with either one of the following, which McGarnagle already suggested:

  • Changes to the visual tree.
  • Changes to a dependency property/object.

This is plausible because the docs say the following: "Occurs when changes occur that affect whether or not the command should execute."

What I noticed:

  • When binding any property of the Viewmodel, CanExecute only gets fired once at startup. The parameter is null.
  • When binding any other element or a property of this element, CanExecute gets fired twice at startup. The parameter is null the first time and the second time it contains either the element or the property of the specified element.
  • When binding the Button itself {Binding RelativeSource={RelativeSource Mode=Self}}, CanExecute gets fired once at startup and the parameter contains the Button element.

As I said before, this doesn't answer anything, but I thought providing some additional info on this matter wouldn't hurt. If someone finds a definitive answer, providing the why of this behavior, I would certainly appreciate that.

Anyway, I used the first scenario in my own app and restructered the logic so now it's working as I originally intended.

Kaj
  • 333
  • 2
  • 8