Problem with Namescopes in XAML

Mar 16, 2012 at 9:41 AM

Hello,

 

I've recently had a problem with this approach. It is producing errors with Namescope, if you use "x:Name" inside any element of FrontSide or BackSide.

So I "converted" it to a class completely defined in c#, which does the absolutely same thing.

    /// <summary>
    /// Custom UserControl with Front and Backside
    /// to flip content when event occurs
    /// </summary>
    public sealed class FlipControl : UserControl
    {
        /// <summary>
        /// Storyboard for Flip
        /// </summary>
        public Storyboard StoryFlip;

        /// <summary>
        /// Storyboard to flip back
        /// </summary>
        public Storyboard StoryFlipBack;

        /// <summary>
        /// Rotation through axis
        /// </summary>
        private AxisAngleRotation3D axisAngleRotation3D;

        /// <summary>
        /// Second rotation through axis
        /// </summary>
        private AxisAngleRotation3D axisAngleRotation3D2;

        /// <summary>
        /// Front side
        /// </summary>
        private Viewport2DVisual3D side1;

        /// <summary>
        /// Back side
        /// </summary>
        private Viewport2DVisual3D side2;

        /// <summary>
        /// Initializes a new instance of the <see cref="FlipControl"/> class.
        /// </summary>
        public FlipControl()
        {
            #region Side1
            this.side1 = new Viewport2DVisual3D();
            axisAngleRotation3D = new AxisAngleRotation3D(new Vector3D(0, 1, 0), 0);
            this.side1.Transform = new RotateTransform3D(){Rotation = axisAngleRotation3D};
            this.side1.Geometry = new MeshGeometry3D()
            {
                Positions = new Point3DCollection() { new Point3D(-1, 1, 0), new Point3D(-1, -1, 0), new Point3D(1, -1, 0), new Point3D(1, 1, 0) },
                TextureCoordinates = new PointCollection() { new Point(0, 0), new Point(0, 1), new Point(1, 1), new Point(1, 0) },
                TriangleIndices = new Int32Collection() { 0, 1, 2, 0, 2, 3 }
            };
            DiffuseMaterial diffuseMaterial = new DiffuseMaterial(new SolidColorBrush(Colors.White));
            diffuseMaterial.SetValue(Viewport2DVisual3D.IsVisualHostMaterialProperty, true);
            this.side1.Material = diffuseMaterial;
            #endregion

            #region Side2
            this.side2 = new Viewport2DVisual3D();
            axisAngleRotation3D2 = new AxisAngleRotation3D(new Vector3D(0, 1, 0), 180);
            this.side2.Transform = new RotateTransform3D(){Rotation = axisAngleRotation3D2};
            this.side2.Geometry = new MeshGeometry3D()
            {
                Positions = new Point3DCollection() { new Point3D(-1, 1, 0), new Point3D(-1, -1, 0), new Point3D(1, -1, 0), new Point3D(1, 1, 0) },
                TextureCoordinates = new PointCollection() { new Point(0, 0), new Point(0, 1), new Point(1, 1), new Point(1, 0) },
                TriangleIndices = new Int32Collection() { 0, 1, 2, 0, 2, 3 }
            };
            diffuseMaterial.SetValue(Viewport2DVisual3D.IsVisualHostMaterialProperty, true);
            this.side2.Material = diffuseMaterial;
            #endregion

            this.InitializeStories();
            Viewport3D viewport3D = new Viewport3D
                                        {
                                            Camera = new PerspectiveCamera() 
                                            { Position = new Point3D(0, 0, 4) }
                                        };

            #region light
            ModelVisual3D modelVisual3D = new ModelVisual3D();
            modelVisual3D.Content = new AmbientLight(Colors.White);
            viewport3D.Children.Add(modelVisual3D);
            #endregion

            viewport3D.Children.Add(this.side1);
            viewport3D.Children.Add(this.side2);
            AddChild(viewport3D);
        }

        private void InitializeStories()
        {
            #region StoryFlip
            DoubleAnimationUsingKeyFrames doubleAnimationUsingKeyFrames = new DoubleAnimationUsingKeyFrames();
            //register new NameScope for this
            NameScope.SetNameScope(this, new NameScope()); 
            RegisterName("axisAngleRotation3D", axisAngleRotation3D);
            RegisterName("axisAngleRotation3D2", axisAngleRotation3D2);

            /// Target can not be declared with SetTarget, see http://connect.microsoft.com/VisualStudio/feedback/details/723701/storyboard-settarget-only-works-on-uielements-but-throws-no-exception
            Storyboard.SetTargetName(doubleAnimationUsingKeyFrames, "axisAngleRotation3D");
            Storyboard.SetTargetProperty(doubleAnimationUsingKeyFrames, new PropertyPath(AxisAngleRotation3D.AngleProperty));
            doubleAnimationUsingKeyFrames.KeyFrames.Add(new SplineDoubleKeyFrame()
            {
                KeyTime = KeyTime.FromTimeSpan(new TimeSpan(0, 0, 1)),
                KeySpline = new KeySpline(0, 0, 0, 1),
                Value = 180
            });
            DoubleAnimationUsingKeyFrames doubleAnimationUsingKeyFrames2 = new DoubleAnimationUsingKeyFrames();
            Storyboard.SetTargetName(doubleAnimationUsingKeyFrames2, "axisAngleRotation3D2");
            Storyboard.SetTargetProperty(doubleAnimationUsingKeyFrames2, new PropertyPath(AxisAngleRotation3D.AngleProperty));
            
            doubleAnimationUsingKeyFrames2.KeyFrames.Add(new SplineDoubleKeyFrame()
            {
                KeyTime = KeyTime.FromTimeSpan(new TimeSpan(0, 0, 1)),
                KeySpline = new KeySpline(0, 0, 0, 1),
                Value = 360
            });
            StoryFlip = new Storyboard
                            {
                                Children = new TimelineCollection { doubleAnimationUsingKeyFrames, doubleAnimationUsingKeyFrames2 }
                            };

            #endregion

            #region StoryFlipBack
            DoubleAnimationUsingKeyFrames doubleAnimationUsingKeyFrames3 = new DoubleAnimationUsingKeyFrames();
            Storyboard.SetTargetProperty(doubleAnimationUsingKeyFrames3, new PropertyPath(AxisAngleRotation3D.AngleProperty));
            Storyboard.SetTargetName(doubleAnimationUsingKeyFrames3, "axisAngleRotation3D");
            doubleAnimationUsingKeyFrames3.KeyFrames.Add(new SplineDoubleKeyFrame()
            {
                KeyTime = KeyTime.FromTimeSpan(new TimeSpan(0, 0, 1)),
                KeySpline = new KeySpline(0, 0, 0, 1),
                Value = 0
            });
            DoubleAnimationUsingKeyFrames doubleAnimationUsingKeyFrames4 = new DoubleAnimationUsingKeyFrames();
            Storyboard.SetTargetProperty(doubleAnimationUsingKeyFrames4, new PropertyPath(AxisAngleRotation3D.AngleProperty));
            Storyboard.SetTargetName(doubleAnimationUsingKeyFrames4, "axisAngleRotation3D2");
            doubleAnimationUsingKeyFrames4.KeyFrames.Add(new SplineDoubleKeyFrame()
            {
                KeyTime = KeyTime.FromTimeSpan(new TimeSpan(0, 0, 1)),
                KeySpline = new KeySpline(0, 0, 0, 1),
                Value = 180
            });
            StoryFlipBack = new Storyboard
                                {
                                    Children = new TimelineCollection { doubleAnimationUsingKeyFrames3, doubleAnimationUsingKeyFrames4 }
                                };

            #endregion
        }

        /// <summary>
        /// Gets or sets the front side.
        /// </summary>
        /// <value>
        /// The front side.
        /// </value>
        public Visual FrontSide
        {
            get
            {
                return this.side1.Visual;
            }
            set
            {
                UIElement Elem;
                Storyboard Animation;

                side1.Visual = value;
                Elem = side1.Visual as UIElement;

                if (Elem != null)
                {
                    Elem.PreviewMouseDown += (sender, e) =>
                    {
                        Animation = StoryFlip;

                        if (Animation != null && e.ClickCount >= 3)
                        {
                            Animation.Begin(this);
                        }
                    };
                }

            }
        }

        /// <summary>
        /// Gets or sets the back side.
        /// </summary>
        /// <value>
        /// The back side.
        /// </value>
        public Visual BackSide
        {
            get
            {
                return side2.Visual;
            }
            set
            {
                UIElement Elem;
                Storyboard Animation;

                side2.Visual = value;
                Elem = side2.Visual as UIElement;

                if (Elem != null)
                {
                    Elem.PreviewMouseDown += (sender, e) =>
                    {
                        Animation = this.StoryFlipBack;

                        if (Animation != null && e.ClickCount >= 3)
                        {
                            Animation.Begin(this);
                        }
                    };
                }

            }
        }
    }

There where some problems with SetTarget and SetTargetName but I found a workaround.

And the Event I used to "flip" is TripleClick.

 

Greetings