Search code examples
c#wpfcontroltemplateframeworkelementfactory

Assign Path data to Thumb control programmatically and add it to Canvas


What I am trying to do is to create a rectangle programmatically at a particular location and I want to assign that to the Thumb control before adding to the Canvas. The reason is I want to implement a drag and drop later. But problem with this code below is I never see anything inside the Canvas please help. When I try to debug I see no data in the fact variable and t.HasContent is false.

 public void DrawShape2()
        {
            Thumb th = new Thumb();

            Path myPath1 = new Path();
            myPath1.Stroke = Brushes.Black;
            myPath1.StrokeThickness = 1;
            SolidColorBrush mySolidColorBrush = new SolidColorBrush();
            mySolidColorBrush.Color = Color.FromArgb(255, 204, 204, 255);
            myPath1.Fill = mySolidColorBrush;

            Point a = new Point(25, 150);
            Point b = new Point(500, 490);

            Rect myRect1 = new Rect(a, b);
            RectangleGeometry myRectangleGeometry1 = new RectangleGeometry();
            myRectangleGeometry1.Rect = myRect1;

            GeometryGroup myGeometryGroup1 = new GeometryGroup();
            myGeometryGroup1.Children.Add(myRectangleGeometry1);

            myPath1.Data = myGeometryGroup1;

            ControlTemplate t = new ControlTemplate();
            var fact = new FrameworkElementFactory(typeof(Path));
            fact.SetValue(Path.DataProperty, myPath1.Data);
            t.VisualTree = fact;
            th.Template = t;
            cnv.Children.Add(th);
        }

Solution

  • The reason why your code isn't working, is because you aren't creating your ControlTemplate correctly.

    NOTE: Microsoft recommends that you create your XAML as a string and then parse it with XamlReader.Parse instead of using FrameworkElementFactory.

    Below are two versions of the code. 1 using XamlReader.Parse and 2 using FrameworkElementFactory.

    XamlReader.Parse

    var th = new Thumb();
    
    var controlTemplate =
        "<ControlTemplate xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" TargetType=\"Thumb\">" +
        "<Path Stroke=\"Black\" StrokeThickness=\"1\" Fill=\"#FFCCCCFF\">" +
        "<Path.Data>" +
        "<GeometryGroup>" +
        "<RectangleGeometry Rect=\"25,150,500,490\"/>" +
        "</GeometryGroup>" +
        "</Path.Data>" +
        "</Path>" +
        "</ControlTemplate>";
    
    th.Template = (ControlTemplate) XamlReader.Parse(controlTemplate);
    
    Canvas.Children.Add(th);
    

    FrameworkElementFactory

    var th = new Thumb();
    
    var a = new Point(25, 150);
    var b = new Point(500, 490);
    
    var myRect1 = new Rect(a, b);
    var myRectangleGeometry1 = new RectangleGeometry {Rect = myRect1};
    
    var myGeometryGroup1 = new GeometryGroup();
    myGeometryGroup1.Children.Add(myRectangleGeometry1);
    
    var t = new ControlTemplate(typeof(Thumb));
    var path = new FrameworkElementFactory(typeof(Path));
    path.SetValue(Shape.StrokeProperty, Brushes.Black);
    path.SetValue(Shape.StrokeThicknessProperty, 1d);
    path.SetValue(Shape.FillProperty, new SolidColorBrush{Color = Color.FromArgb(255, 204, 204, 255)});
    path.SetValue(Path.DataProperty, myGeometryGroup1);
    t.VisualTree = path;
    th.Template = t;
    Canvas.Children.Add(th);
    

    I hope this is helpful.