views:

576

answers:

4

So here is my dilemma, I want to handle view events on my view model, trouble is, in order to add an event handler, my view has to have a code behind file and therefore a class attribute has to be set. I'm 99% sure this is a bad idea, and to be perfectly honest, i'm not even sure how to do it (other than the obvious x:Class="" part) What is the proper way to do this in an MVVM application?

<ResourceDictionary>
    <DataTemplate DataType="{x:Type vm:OutletViewModel}">
        <Button Click="IHaveNoBinding">
    </DataTemplate>
</ResourceDictionary>
+3  A: 

Use commands:

<Button Command="{Binding ACommandOnYourViewModel}"/>

See this post of mine for a useful command implementation you can use in your view models.

Assuming you can't use commands, use attached command behaviors.

HTH, Kent

Kent Boogaart
Alright, assume I can't use commands, Assume it's Textbox.TextChanged
Firoso
Edited accordingly.
Kent Boogaart
For text, use binding:<TextBox Text="{Binding ViewModelPropertyName}"/>
decasteljau
+1  A: 

I use Attached Behaviors. Attached behaviors basically translate events into commands. Check out this link for an example:

http://www.codeproject.com/KB/WPF/AttachedBehaviors.aspx

Here is the code for a TextChangedBehavior.

 public static class TextChangedBehavior
  {
    public static readonly DependencyProperty TextChangedCommandProperty =
        DependencyProperty.RegisterAttached("TextChangedCommand",
                                            typeof(ICommand),
                                            typeof(TextChangedBehavior),
                                            new PropertyMetadata(null, TextChangedCommandChanged));

    public static ICommand GetTextChangedCommand(DependencyObject obj)
    {
      return (ICommand)obj.GetValue(TextChangedCommandProperty);
    }

    public static void SetTextChangedCommand(DependencyObject obj, ICommand value)
    {
      obj.SetValue(TextChangedCommandProperty, value);
    }

    private static void TextChangedCommandChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
      TextBoxBase textBox = obj as TextBoxBase;

      if (textBox != null)
      {
        textBox.TextChanged += new TextChangedEventHandler(HandleTextChanged);
      }
    }

    private static void HandleTextChanged(object sender, TextChangedEventArgs e)
    {
      TextBox textBox = sender as TextBox;
      if (textBox != null)
      {
        ICommand command = GetTextChangedCommand(textBox);
        command.Execute(textBox.Text);
      }
    }
  }

XAML:

<TextBox behavior:TextChangedBehavior.TextChangedCommand="{Binding TextChangedCommand}" />
Shaun Bowe
A: 

Generally I will not use the attached behavior pattern for simple things like this. As a consultant I find It complicates things for newer developers.

So how then do you handle control interaction when no commands are available. Get ready to pick your self up off of the floor :-) I will often times use the code behind for this. The event handler in the code behind handles the event, it gathers any data it needs from the event args and then forwards the request to the View Model. You do not lose much by doing this as most things that do not support ICommand cannot leverage the hide/show/enable/disable anyway.

There are some rules however. The code behind can only be used for control forwarding to the View Model. As long as you don't pass event arguments directly to the View Model I think it is fine to use events in this way. The fact of that matter is in large scale applications you cannot always get away from having code behinds. If you use them as they were intended i.e. page controls I see no harm in doing so.

Brette.Net
A: 

Code behind isn't a bad thing at all. There are enough scenarios where you can't use WPF data binding (e.g. PasswordBox) and then you have to create a code behind file.

How you can use a PasswordBox without binding is shown in the ViewModel example of this project:

WPF Application Framework (WAF)

http://waf.codeplex.com

jbe