Don’t leave my this way!

UPDATE. My Glass library contains an improved version of this behavior. Take a look at it!

Aha! So you just discovered that users tend to break your applications typing everything you could imagine. Validation in Hell!

Imagine you have some information that has to be filled in. For example, this Window tell you to enter a value between 1 and 5.image

It may be not obvious to the user that information is extremely important. So you cannot leave it in an invalid state.

Boy, those mandatory fields must be valid before you go away!

But, how do you keep they into the TextBox? The user types “2000” and suddenly, they change the focus to the Dummy text box.

The required TextBox will show its value is invalid, but maybe the user is happy with that red TextBox and starts to touching here and there with something that is wrong. This can be, of course, perfectly acceptable, but sometimes the information you request just cannot be left in an invalid state.

That is why I made this Interaction Behavior. KeepFocusOnErrorBehavior.

If you attach it to any TextBoxBase (like TextBox), you will notice it will not let you change the focus to another control while it doesn’t pass the validation. Example:


As you can see, this behavior is attached to the TextBox and its ErrorCommand is set to a Command (in a View Model). This command makes it even better, because you can, for example, bind a Command that shows a message indicating that you’re not allowed to go anywhere before entering correct input.

I hope you like it Sonrisa

Here is the code:

public class KeepFocusOnErrorBehavior : Behavior<TextBoxBase> {
        protected override void OnAttached() {

            AssociatedObject.PreviewLostKeyboardFocus += AssociatedObjectOnPreviewLostKeyboardFocus;
            base.OnAttached();

        }

        private void AssociatedObjectOnPreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs keyboardFocusChangedEventArgs) {

            var textBindingExpression = AssociatedObject.GetBindingExpression(TextBox.TextProperty);

            // Forces to update the binding. As we are preventing the focus to be lost, its binding never updates and never recovers from a previous error.
            textBindingExpression.UpdateSource();

            var value = Validation.GetHasError(AssociatedObject);
            if (value) {
                keyboardFocusChangedEventArgs.Handled = true;
                ExecuteErrorCommandIfCanExecute();
            }
        }

        private void ExecuteErrorCommandIfCanExecute() {
            if (ErrorCommand != null) {
                if (ErrorCommand.CanExecute(ErrorCommandParameter))
                    ErrorCommand.Execute(ErrorCommandParameter);
            }
        }

        #region ShowErrorMessageCommand
        public static readonly DependencyProperty ErrorCommandProperty =
          DependencyProperty.Register("ErrorCommand", typeof(ICommand), typeof(KeepFocusOnErrorBehavior),
            new FrameworkPropertyMetadata((ICommand)null));

        public ICommand ErrorCommand {
            get { return (ICommand)GetValue(ErrorCommandProperty); }
            set { SetValue(ErrorCommandProperty, value); }
        }

        #endregion

        #region ErrorCommandParameter
        public static readonly DependencyProperty ErrorCommandParameterProperty =
          DependencyProperty.Register("ErrorCommandParameter", typeof(object), typeof(KeepFocusOnErrorBehavior),
            new FrameworkPropertyMetadata((object)null));

        public object ErrorCommandParameter {
            get { return (object)GetValue(ErrorCommandParameterProperty); }
            set { SetValue(ErrorCommandParameterProperty, value); }
        }

        #endregion

    }
Anuncios

Ese TextBox que crece indefinidamente

Te encuentras con la situación en que escribiendo en un TextBox tal que así:

image

Te pasas de la raya y escribes un poco más. De repente ocurre esto:

image

Una barrita de desplazamiento, o también llamada “ScrollBar” te la meterá doblada y arruinará tu layout a la primera oportunidad.

Para que esto no ocurra y la cosa crezca verticalmente (el TextBox), dando como resultado esta captura tan interesante…

image

… deberías poner un ScrollViewer.HorizontalScrollBarVisibility=”Disabled” en el contenedor apropiado, ejemplo:

<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled" HorizontalContentAlignment="Stretch">
	<Grid>
		<Grid.ColumnDefinitions>
			<ColumnDefinition Width="Auto" />
			<ColumnDefinition Width="*" />
		</Grid.ColumnDefinitions>
		<TextBox Text="Hola tío"/>
		<TextBox Grid.Column="1" TextWrapping="Wrap" Text="TextBlock" />
	</Grid>
</ListBox>

¡Y así, la fiereza es dada!