Search code examples
c#propertygridxceed

c# xceed PropertyGrid work with System.Windows.Media.PointCollection


I have a problem. I using property grid to set Collection of points, but program give me InvalidOperationException: collection has been changed…

I try use Custom converter but no result :(

What am I doing wrong?

Could someone write the correct procedure to solve this?

Thanks very much for answer.

I wrote simple program, this is not from my project(my project is top secret :)), but it works on a similar logic.

XAML:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication1"
        xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="600">
    <Grid>
        <xctk:PropertyGrid x:Name="workplace_property" ShowSearchBox="False" Background="WhiteSmoke" UpdateTextBoxSourceOnEnterKey="True" ShowAdvancedOptions="True" SnapsToDevicePixels="True" IsMiscCategoryLabelHidden="True" SelectedObject="{Binding}" HorizontalAlignment="Right" Width="251"/>
        <Canvas Name="myCanvas" Margin="0">
        </Canvas>
    </Grid>
</Window>

CS:

using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        public Polyline drawobj;
        public MainWindow()
        {
            InitializeComponent();

            drawobj = new Polyline();
            drawobj.Points = new PointCollection() { new Point(10, 20), new Point(40, 20), new Point(150, 150) };
            drawobj.StrokeThickness = 2;
            drawobj.Stroke = new SolidColorBrush(Colors.Black);

            myCanvas.Children.Add(drawobj);

            workplace_property.SelectedObject = new polyline_property(drawobj);   
        }
    }

    public class polyline_property
    {
        private Polyline drawobj;

        public polyline_property(Polyline obj)
        {
            drawobj = obj;
        }

        public PointCollection Points
        {
            get
            {
                return drawobj.Points;
            }
            set
            {
                drawobj.Points = value;
            }
        }

        public Color Color
        {
            get
            {
                return ((SolidColorBrush)drawobj.Stroke).Color;
            }
            set
            {
                ((SolidColorBrush)drawobj.Stroke).Color = value;
            }
        }

        public Double StrokeThickness
        {
            get
            {
                return drawobj.StrokeThickness;
            }
            set
            {
                drawobj.StrokeThickness = value;
            }
        }

        public DoubleCollection StrokeDashArray
        {
            get
            {
                return drawobj.StrokeDashArray;
            }
            set
            {
                drawobj.StrokeDashArray = value;
            }
        }

        public PenLineCap StrokeDashCap
        {
            get
            {
                return drawobj.StrokeDashCap;
            }
            set
            {
                drawobj.StrokeDashCap = value;
            }
        }

        public Double StrokeDashOffset
        {
            get
            {
                return drawobj.StrokeDashOffset;
            }
            set
            {
                drawobj.StrokeDashOffset = value;
            }
        }
    }
}

Solution

  • I modify class with properties, and works great! Using BindingList with custom event, which save PointCollection to object.

    using System;
    using System.ComponentModel;
    using System.Windows;
    using System.Windows.Media;
    using System.Windows.Shapes;
    using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
    
    namespace RCFramework
    {
        public class polyline_property
        {
            private Polyline drawobj;
            private BindingList<custom_point> point_collection;
    
            public polyline_property(Polyline obj)
            {
                drawobj = obj;
    
                point_collection = new BindingList<custom_point>();
                point_collection.AllowEdit = true;
                point_collection.AllowNew = true;
                point_collection.AllowRemove = true;
    
                foreach (Point pnt in drawobj.Points)
                {
                    custom_point newpnt = new custom_point();
                    newpnt.X = pnt.X;
                    newpnt.Y = pnt.Y;
                    point_collection.Add(newpnt);
                }
    
                point_collection.RaiseListChangedEvents = true;
                point_collection.ListChanged += point_collection_ListChanged;
            }
    
            private void point_collection_ListChanged(object sender, ListChangedEventArgs e)
            {
                PointCollection pcol = new PointCollection();
                foreach (custom_point pnt in point_collection)
                {
                    pcol.Add(new Point(pnt.X, pnt.Y));
                }
                drawobj.Points = pcol;
            }
    
    
            public BindingList<custom_point> Points
            {
                get
                {
                    point_collection.RaiseListChangedEvents = false;
                    point_collection.Clear();
                    foreach (Point pnt in drawobj.Points)
                    {
                        custom_point newpnt = new custom_point();
                        newpnt.X = pnt.X;
                        newpnt.Y = pnt.Y;
                        point_collection.Add(newpnt);
                    }
                    point_collection.RaiseListChangedEvents = true;
                    return point_collection;
                }
                set
                {
    
                }
            }
    
            public Color Color
            {
                get
                {
                    return ((SolidColorBrush)drawobj.Stroke).Color;
                }
                set
                {
                    ((SolidColorBrush)drawobj.Stroke).Color = value;
                }
            }
    
            public Double StrokeThickness
            {
                get
                {
                    return drawobj.StrokeThickness;
                }
                set
                {
                    drawobj.StrokeThickness = value;
                }
            }
    
            public DoubleCollection StrokeDashArray
            {
                get
                {
                    return drawobj.StrokeDashArray;
                }
                set
                {
                    drawobj.StrokeDashArray = value;
                }
            }
    
            public PenLineCap StrokeDashCap
            {
                get
                {
                    return drawobj.StrokeDashCap;
                }
                set
                {
                    drawobj.StrokeDashCap = value;
                }
            }
    
            public Double StrokeDashOffset
            {
                get
                {
                    return drawobj.StrokeDashOffset;
                }
                set
                {
                    drawobj.StrokeDashOffset = value;
                }
            }
        }
    
        public class custom_point
        {
            public Double X { get; set; }
            public Double Y { get; set; }
    
            public custom_point()
            {
    
            }
        }
    }