Category Archives: XAML

ASP.NET Adventure. My new project using SignalR.

image

I’m currently working on a set of applications to handle the main tasks of my family’s restaurant. This is a snapshot of the client for the kitchen. It’s on a very early state, but you can mark product orders as “Done”. It uses Entity Framework and some concepts of Domain-Driven Design. It’s also using Windows 8.1 and Windows Phone 8 for the clients (the waiters will have another kind of client to request orders to the kitchen.

SignalR is needed to notify waiters when an order is ready (or even when a product is ready). I wanted to share the progress on this! Smile For the moment, I think Windows 8 is a bit limiting in terms of layout. WPF is far more complete. But it doesn’t feel bad at all. I think the lack of Triggers for Styles will be a big headache, but some people are working on a MVVM-friendly way to face this using Visual States.

I also feel the asynchrony will be a major let down in a later stage of the solution, but with a bit of help, it can be done. I want to start it simple!

I hope you like it. The background is a bit lame, but I like blue hues! haha Open-mouthed smile

Hey, my picture appears in each order, but a picture of each waiter will appear in a few iterations, of course Smile with tongue out

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

    }

Efecto DockPanel, pero sin chuchurrirse

image

Con un DockPanel la cosa se chuchurre de mala manera.

Si queremos que esto no suceda y que quien mande sea el “UpDown” (a la derecha de las flechitas), debemos poner un Grid parecido al siguiente (el ejemplo de las flechitas es solamente para que ser viera lo que quiero decir).

 <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <TextBlock TextTrimming="CharacterEllipsis" Text="{Binding Name}" Margin="0,0,2,0" />
                <UniformGrid HorizontalAlignment="Right" Grid.Column="1" Rows="1">
                    <UniformGrid.Resources>
                        <Style TargetType="TextBlock">
                            <Setter Property="Margin" Value="2,0,2,0" />
                        </Style>
                    </UniformGrid.Resources>
                    <TextBlock TextTrimming="CharacterEllipsis" x:Name="Bold" Text="{Binding Path=Bold, Source={StaticResource Localization}}" Visibility="Collapsed" />
                    <TextBlock TextTrimming="CharacterEllipsis" x:Name="Italic" Text="{Binding Path=Italic, Source={StaticResource Localization}}" Visibility="Collapsed" />
                </UniformGrid>
            </Grid>

Realmente necesitábamos una grid. El elemento que manda en el layout (el que debe ser visible siempre que se pueda) no llevará ninguna alineación. El elemento de menos prioridad tendrá la alineación que deseemos.

Databinding to Structs

Well, this is going to be rude: Binding to struct types can be a tricky. You will absolutely love when the UI just ignores every change. It refuses to update and eventually you’ll get mad about this, wondering why those nice bindings to Paddings or Margins are ignored. It’s kind of frustrating.

This boils down the nature of structs. They are value types and they’re taken as a whole by the dependency property mechanism.

When you define a DP that carries a struct, any binding to a child attribute that composes that struct reflects the actual value of that member, but ONLY when the struct is replaced by another “instance” of the struct (another value). Changing its attributes will not notify any change (Property Changed callbacks won’t be called).

For instance, you have a DP with a Point and a binding link this:

Text=”{Binding Path=MyPoint.X}”

Suppose that the X value of the struct is modified the some other binding (or whatever). You may expect the Text to reflect the X value anytime it is changed, but no way! WPF will blow you off, sticking out its long and complex tongue.

This is (not easily) solved replacing the value of the struct whenever you want the change to be reflected in the UI. “What? you mean that I have to care about changes in every member of the struct in order to have the bindings fresh like my cotton underwear”. Yes, that’s it!

Pretty annoying! but this is the price you have to pay for using those cute simplistic and handy structs!

Don’t forget it. Never! You sweated too much because of this Sonrisa! I hope you finally understood, Suppa JMN!

Y todo esto para tirarme el pegote de escribir en Inglés, ¡copón! Bueno, también es verdad que si algún lobo de mar angloparlante viene a mi blog por alguna casualidad de la vida, quizá le guste entender algo, ¿no?

¡Menús dinámicos! Harás cacota si no sabes esto

Imagina lo siguiente: Tienes un menú que se compone mediante un binding, pero resulta que es una combinación de varias colecciones. Por ejemplo, un menú que presenta una serie de opciones fijas (o variables), y entre medias, una colección enlazada con Binding. Pues colleiga, ¡se hace así!

<MenuItem.ItemsSource>

    <CompositeCollection>

        <!--<MenuItem Header="Menú de coña1" />

        <MenuItem Header="Menú de coña2" />

        <Separator/>-->

        <CollectionContainer Collection="{Binding Source={StaticResource EditorsCollectionViewSource}}" />

        <!--<Separator/>

        <MenuItem Header="Menú de coña3" />-->

    </CompositeCollection>

</MenuItem.ItemsSource>

Con la ayuda de un lobo de mar que dejó su info en Internet, ¡como los buenos samaritanos de Dios!

http://wilberbeast.com/2011/05/31/compositecollection-binding-problem/#comment-2337

En referencia a este error guarrero que da si no enlazas con la CollectionViewSource:

Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=FilterOptions; DataItem=null; target element is ‘CollectionContainer’ (HashCode=23627591); target property is ‘Collection’ (type ‘IEnumerable’)

¡Buen provecho, y una patada en el pecho!

EventToCommand

 

<i:Interaction.Triggers>

       <i:EventTrigger EventName="MouseEnter">

           <cmd:EventToCommand Command="{Binding TestCommand,

                                         Mode=OneWay}"

              CommandParameter="{Binding Text,

                                 ElementName=MyTextBox,

                                 Mode=OneWay}"

              MustToggleIsEnabledValue="True" />

       </i:EventTrigger>

   </i:Interaction.Triggers>