views:

179

answers:

2

I created an attached property, AttachedBehaviorsManager.Behaviors that is to be used as an MVVM helper class that ties events to commands. The property is of type BehaviorCollection (a wrapper for ObservableCollection). My issue is that the Binding for the Behavior's Command always winds up being null. When used on the buttons it works just fine though.

My question is why am I losing my DataContext on items inside of the collection, and how can I fix it?

<UserControl x:Class="SimpleMVVM.View.MyControlWithButtons"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:behaviors="clr-namespace:SimpleMVVM.Behaviors"
    xmlns:con="clr-namespace:SimpleMVVM.Converters"
Height="300" Width="300">
<StackPanel>
  <Button Height="20" Command="{Binding Path=SetTextCommand}" CommandParameter="A" Content="Button A" />
  <Button Height="20" Command="{Binding Path=SetTextCommand}" CommandParameter="B" Content="Button B"/>
 <TextBox x:Name="tb" Text="{Binding Path=LabelText}">
  <behaviors:AttachedBehaviorsManager.Behaviors>
   <behaviors:BehaviorCollection>
    <behaviors:Behavior Command="{Binding Path=SetTextCommand}" CommandParameter="A" EventName="GotFocus"/>
   </behaviors:BehaviorCollection>
  </behaviors:AttachedBehaviorsManager.Behaviors>
 </TextBox>
</StackPanel>

A: 

Why are you binding to the command? Commands are meant to be setup this way:

<Button Command="ApplicationCommands.Open"/>

Suppose you define a command class like so:

namespace SimpleMVVM.Behaviors {
    public static class SimpleMvvmCommands {
        public static RoutedUICommand SetTextCommand { get; }
    }
}

You would use it like so:

<Button Command="behaviors:SimpleMvvmCommands.SetTextCommand"/>

The MVVM pattern isn't applicable the way you're using it. You'd put the command handler on the VM, but commands themselves are meant to be in the static context. Please refer to the documentation on MSDN for further information.

Daniel Moore
A: 

You bind to the command because this is using the MVVM (Model-View-ViewModel) pattern. The datacontext of this user control is a ViewModel object containing a property that exposes the command. Commands do not need to be public static objects.

The buttons in the shown code have no problem executing. They are bound to to the SetTextCommand in the viewmodel:

class MyControlViewModel : ViewModelBase
{
    ICommand setTextCommand;
    string labelText;

    public ICommand SetTextCommand
    {
        get
        {
            if (setTextCommand == null)
                setTextCommand = new RelayCommand(x => setText((string)x));
            return setTextCommand;
        }
    }
    //LabelText Property Code...

    void setText(string text)
    {
        LabelText = "You clicked: " + text;
    }
}

The problem is that the binding to the same SetTextCommand that works in the buttons is not recognized in the behavior:Behavior.

statenjason