Custom Layouts en WPF

Hemos estado viendo en los anteriores post los diferentes layouts que viene en WPF, pero también podremos crear nuestro porpio contendor y que funcione como nosotros diseñemos. Esto es una gran flexibilidad a la hora de diseñar nuestra aplicación, para ello deberemos crear una clase que derive de Panel que explique en este post. Si recordamos los conceptos mas importantes son:

Measure

En estado de medición  (Measure) el contenedor comprueba por cada uno de
los  elementos  hijos  su  tamaño  deseado,  es  decir,  les  “pregunta”  que  tamaño
pretende ocupar en el contenedor.

Arrange

En este estado de distribución (Arrange), el contenedor coloca a cada uno de
los elementos hijos en su posición apropiada.

Ya que deberemos sobreescribir los metodos MeasureOverride y ArrangeOverride para programar como se comporta nuestro control.

Un ejemplo muy sencillo es

public class MySimplePanel : Panel
    {
        // Make the panel as big as the biggest element
        protected override Size MeasureOverride(Size availableSize)
        {
            Size maxSize = new Size();

            foreach (UIElement child in InternalChildern)
            {
                maxSize.Height = Math.Max(child.DesiredSize.Height, maxSize.Height);
                maxSize.Width = Math.Max(child.DesiredSize.Width, maxSize.Width);
            }
        }

        // Arrange the child elements to their final position
        protected override Size ArrangeOverride(Size finalSize)
        {
            foreach (UIElement child in InternalChildern)
            {
                child.Arrange(new Rect(finalSize));
            }
        }
    }

Podéis probar lo que hace.

 

Uno mas complejo es el que he llamado AnimatedWrapPanel, se comporta como un WraPanel pero cuando pasas el raton por encima de u elemento se realiza una animación para que se vea mas grande y cuando sale el ratón vuelve a su tamaño

 

 /// <summary>
    /// Wrap Panel que crea una animacion cuando se construyen,
    /// los items van desde la posicion 0 hasta su lugar
    /// </summary>
    public class AnimatedWrapPanel : Panel
    {
        private TimeSpan animationLength =
            TimeSpan.FromMilliseconds(500);
        private TimeSpan animationSelected =
          TimeSpan.FromMilliseconds(200);
        private double scaleselected = 1.2;
        private Size sizecontrol = new Size();
        private bool animating = false;
        public AnimatedWrapPanel()
        {
            this.MouseEnter += new MouseEventHandler(AnimatedWrapPanel_MouseEnter);
            this.MouseLeave += new MouseEventHandler(AnimatedWrapPanel_MouseLeave);
            this.MouseMove += new MouseEventHandler(AnimatedWrapPanel_MouseMove);
        }

        void AnimatedWrapPanel_MouseMove(object sender, MouseEventArgs e)
        {
            if (!animating)
                AnimateSelected();
        }

        private void AnimateSelected()
        {
            if (this.Children == null || this.Children.Count == 0)
                return;
            animating = true;

            if (this.IsMouseOver)
            {
                double x = Mouse.GetPosition(this).X;
                foreach (FrameworkElement child in this.Children)
                {
                    if (child.IsMouseOver)
                    {

                        if (child.RenderTransform is TranslateTransform)
                        {
                            TranslateTransform trans = child.RenderTransform as TranslateTransform;
                            TransformGroup transgroup = new TransformGroup();
                            transgroup.Children.Add(trans);
                            ScaleTransform scale = new ScaleTransform();
                            scale.CenterX = trans.X;
                            scale.CenterY = trans.Y;
                            transgroup.Children.Add(scale);
                            child.RenderTransform = transgroup;
                            DoubleAnimation da = MakeAnimation(scaleselected);


                            scale.BeginAnimation(ScaleTransform.ScaleXProperty, da, HandoffBehavior.SnapshotAndReplace);

                            scale.BeginAnimation(ScaleTransform.ScaleYProperty,
                           da,
                            HandoffBehavior.SnapshotAndReplace);



                        }
                        else if (child.RenderTransform is TransformGroup)
                        {
                            TransformGroup transgroup = child.RenderTransform as TransformGroup;
                            ScaleTransform scale = transgroup.Children[1] as ScaleTransform;
                            TranslateTransform trans = transgroup.Children[0] as TranslateTransform;

                            DoubleAnimation da = MakeAnimation(scaleselected);


                            scale.BeginAnimation(ScaleTransform.ScaleXProperty,
                         da,
                            HandoffBehavior.Compose);
                            scale.BeginAnimation(ScaleTransform.ScaleYProperty,
                            da,
                            HandoffBehavior.Compose);
                        }
                    }
                    else if (child.RenderTransform is TransformGroup)
                    {
                        TransformGroup transgroup = child.RenderTransform as TransformGroup;
                        ScaleTransform scale = transgroup.Children[1] as ScaleTransform;
                        TranslateTransform trans = transgroup.Children[0] as TranslateTransform;

                        if (scale.ScaleX == 1.2)
                        {

                            scale.BeginAnimation(ScaleTransform.ScaleXProperty,
                            new DoubleAnimation(1, animationSelected),
                            HandoffBehavior.Compose);
                            scale.BeginAnimation(ScaleTransform.ScaleYProperty,
                            new DoubleAnimation(1, animationSelected),
                            HandoffBehavior.Compose);

                        }

                    }

                }
            }

            animation_Completed(null, null);
        }

        private DoubleAnimation MakeAnimation(double to)
        {
            DoubleAnimation da = new DoubleAnimation(to, animationSelected);
            da.AccelerationRatio = 0.8;
            da.DecelerationRatio = 0.2;
            return da;
        }
        void animation_Completed(object sender, EventArgs e)
        {
            animating = false;
        }
        void AnimatedWrapPanel_MouseLeave(object sender, MouseEventArgs e)
        {
            AnimateSelected();
        }

        void AnimatedWrapPanel_MouseEnter(object sender, MouseEventArgs e)
        {
            AnimateSelected();
        }
        protected override Size MeasureOverride(Size availableSize)
        {
            Size infiniteSize = new Size(double.PositiveInfinity,
                double.PositiveInfinity);
            double curX = 0, curY = 0, curLineHeight = 0;
            foreach (UIElement child in Children)
            {
                child.Measure(infiniteSize);

                if (curX + child.DesiredSize.Width > availableSize.Width)
                { //Siguiente lineaa
                    curY += curLineHeight;
                    curX = 0;
                    curLineHeight = 0;
                }

                curX += child.DesiredSize.Width;
                if (child.DesiredSize.Height > curLineHeight)
                    curLineHeight = child.DesiredSize.Height;
            }

            curY += curLineHeight;

            Size resultSize = new Size();
            resultSize.Width = double.IsPositiveInfinity(
                availableSize.Width) ? curX : availableSize.Width;
            resultSize.Height = double.IsPositiveInfinity(
                availableSize.Height) ? curY : availableSize.Height;

            return resultSize;
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            if (this.Children == null || this.Children.Count == 0)
                return finalSize;

            TranslateTransform trans = null;
            double curX = 0, curY = 0, curLineHeight = 0;
            int zindexposition = Children.Count;
            foreach (UIElement child in Children)
            {
                child.SetValue(ZIndexProperty, zindexposition);
                zindexposition -= 1;
                trans = child.RenderTransform as TranslateTransform;

                if (trans == null)
                {
                    child.RenderTransformOrigin = new Point(0, 0);
                    trans = new TranslateTransform();
                    child.RenderTransform = trans;
                }

                if (curX + child.DesiredSize.Width > finalSize.Width)
                { //Siguiente Linea
                    curY += curLineHeight;
                    curX = 0;
                    curLineHeight = 0;
                }

                child.Arrange(new Rect(0, 0, child.DesiredSize.Width,
                    child.DesiredSize.Height));

                trans.BeginAnimation(TranslateTransform.XProperty,
                    new DoubleAnimation(curX, animationLength),
                    HandoffBehavior.Compose);

                trans.BeginAnimation(TranslateTransform.YProperty,
                    new DoubleAnimation(curY, animationLength),
                    HandoffBehavior.Compose);

                curX += child.DesiredSize.Width;
                if (child.DesiredSize.Height > curLineHeight)
                    curLineHeight = child.DesiredSize.Height;
            }
            sizecontrol = finalSize;
            return finalSize;
        }
        public void Animate()
        {
            TranslateTransform trans = null;
            double curX = 0, curY = 0, curLineHeight = 0;

            foreach (UIElement child in Children)
            {
                child.RenderTransform = null;
                trans = child.RenderTransform as TranslateTransform;

                if (trans == null)
                {
                    child.RenderTransformOrigin = new Point(0, 0);
                    trans = new TranslateTransform();
                    child.RenderTransform = trans;
                }

                if (curX + child.DesiredSize.Width > sizecontrol.Width)
                { //Siguiente Linea
                    curY += curLineHeight;
                    curX = 0;
                    curLineHeight = 0;
                }

                child.Arrange(new Rect(0, 0, child.DesiredSize.Width,
                    child.DesiredSize.Height));

                trans.BeginAnimation(TranslateTransform.XProperty,
                    new DoubleAnimation(curX, animationLength),
                    HandoffBehavior.Compose);

                trans.BeginAnimation(TranslateTransform.YProperty,
                    new DoubleAnimation(curY, animationLength),
                    HandoffBehavior.Compose);

                curX += child.DesiredSize.Width;
                if (child.DesiredSize.Height > curLineHeight)
                    curLineHeight = child.DesiredSize.Height;
            }
            //this.InvalidateArrange();
        }

    }

El resultado es

 

image

Un comentario sobre “Custom Layouts en WPF”

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *