On Mon, Mar 15, 2010 at 3:54 AM, Josh Smith <flappleja
...@gmail.com> wrote:
> A while back Dr. WPF graced us with his clever hack of controlling input
> focus from VM objects. It involved hijacking the VM's IDataErrorInfo
> implementation, and doing all sorts of evil-genius stuff to make the input
> caret move to the correct element. Today while I was *trying* to read a
> great novel, I couldn't stop thinking about another way to control input
> focus from a viewmodel object.
> I put the novel down and did a quick spike of the idea. The source code is
> attached (rename it from .DOC to .ZIP since gmail is terrified of ZIP files
> for some reason). Here's the general idea...
> Implement this interface on your VM class:
> /// <summary>
> /// Implemented by a ViewModel that needs to control
> /// where input focus is in a View.
> /// </summary>
> public interface IFocusController
> {
> /// <summary>
> /// Raised when the input focus should move to
> /// a control whose 'active' dependency property
> /// is bound to the specified property.
> /// </summary>
> event EventHandler<MoveFocusEventArgs> MoveFocus;
> }
> Next, in your VM object (which might implement IDataErrorInfo), do
> something like this to support a Save button:
> public ICommand SaveCommand
> {
> get { return new RelayCommand(this.Save); }
> }
> void Save()
> {
> if (this.HasError)
> {
> // The Error property knows which property is invalid.
> this.RaiseMoveFocus(this.Error);
> }
> else
> {
> // Save to database...
> System.Windows.MessageBox.Show("Saved");
> }
> }
> bool HasError
> {
> get { return _validatedProperties.Any(prop =>
> !String.IsNullOrEmpty(this[prop])); }
> }
> public event EventHandler<MoveFocusEventArgs> MoveFocus;
> void RaiseMoveFocus(string focusedProperty)
> {
> var handler = this.MoveFocus;
> if (handler != null)
> {
> handler(this, new MoveFocusEventArgs(focusedProperty));
> }
> }
> Lastly, in your View, use my terribly(?) named attached property to specify
> which DP on your elements is bound to the validated property of the VM, for
> example:
> <TextBox
> Text="{Binding Path=FirstName, ValidatesOnDataErrors=True}"
> *local:FocusControl.ValidatedProperty="TextBox.Text"*
> />
> I'm not sure that I like this approach yet. It's a pretty important topic,
> so I thought I'd share this out amongst the Disciples for feedback.
> Thanks,
> Josh
--