C# 如何在WPF/C中创建自定义MultiSelector/ItemsControl

C# 如何在WPF/C中创建自定义MultiSelector/ItemsControl,c#,wpf,custom-controls,itemscontrol,C#,Wpf,Custom Controls,Itemscontrol,我正在尝试用C/WPF创建一个图表应用程序。虽然我不想克隆它,但我所追求的有点类似于MicrosoftVisio。我在编写代码的时候写了这个问题,把所有的问题都写进去,以防有人发现它有用。也许我想得太多了,但我觉得我可以在键盘上吐出更好的代码,所以请随时就您捕捉到的每个细节给出任何建议:- 简言之: 为什么所有项目都定位在0,0 代码: 好的,这样的想法是Diagram:ItemsControl将其项放置在画布面板上的item DiagramItem.Location中定义的位置。当我改变图表项

我正在尝试用C/WPF创建一个图表应用程序。虽然我不想克隆它,但我所追求的有点类似于MicrosoftVisio。我在编写代码的时候写了这个问题,把所有的问题都写进去,以防有人发现它有用。也许我想得太多了,但我觉得我可以在键盘上吐出更好的代码,所以请随时就您捕捉到的每个细节给出任何建议:-

简言之: 为什么所有项目都定位在0,0

代码: 好的,这样的想法是Diagram:ItemsControl将其项放置在画布面板上的item DiagramItem.Location中定义的位置。当我改变图表项目中的X属性时,图表会在X轴上移动项目

注意:MultiSelector源于ItemsControl和Selector,仅在此处使用,因为我需要显示的项目是可选的

请注意,如果可能的话,我不想使用xaml

总之: 用户看到的图实例具有以下要求:

有多个诊断项。 用户可以选择多个诊断项。 图表项可以调整大小、旋转和拖动到图表上的任何位置。 可以使用键盘在诊断项之间导航。 我基本上有两门课,可能还有三门课与这个问题有关

图表扩展System.Windows.Controls.Primitives.MultiSelector:Selector:ItemsControl DiagramItem扩展ContentControl或某些其他控件 Diagram.ItemsPanel又名显示项目的可视面板,应该是支持绝对定位的面板,如画布

我应该如何实现从MultiSelector派生的类,以及您可以指出哪些资源与此问题相关

<> P>在实现自定义多选择器/ItMsCube时必须考虑什么?

资源:

我发现与我的问题相关的资源很少,但我也不确定我应该寻找什么。我已经阅读了使用Reflector的ListBox和ListBoxItem的源代码,但没有发现它非常有用

其他资源:


好的,显然这可以通过使用绑定和属性框架轻松实现

    public class Diagram : MultiSelector
    {
        public Diagram()
        {
           this.CanSelectMultipleItems = true;


            // The canvas supports absolute positioning
            FrameworkElementFactory panel = new FrameworkElementFactory(typeof(Canvas)); 
            this.ItemsPanel = new ItemsPanelTemplate(panel);


            // Tells the container where to position the items
           this.ItemContainerStyle = new Style();
            this.ItemContainerStyle.Setters.Add(new Setter(Canvas.LeftProperty, new Binding("X")));
            this.ItemContainerStyle.Setters.Add(new Setter(Canvas.TopProperty, new Binding("Y")));
        }


        protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
        {
            FrameworkElement contentitem = element as FrameworkElement;

            Binding leftBinding = new Binding("XProperty");
            leftBinding.Source = contentitem;

            Binding topBinding = new Binding("YProperty");
            topBinding.Source = contentitem;

            contentitem.SetBinding(Canvas.LeftProperty, leftBinding);
            contentitem.SetBinding(Canvas.TopProperty, topBinding);
            base.PrepareContainerForItemOverride(element, item);
        }





 public class DiagramItem : ContentControl
 {
       public static readonly DependencyProperty XProperty;
       public static readonly DependencyProperty YProperty;
       public static readonly RoutedEvent SelectedEvent;
       public static readonly RoutedEvent UnselectedEvent;
       public static readonly DependencyProperty IsSelectedProperty;

       public DiagramItem()
       {
       }

       static DiagramItem()
       {
            XProperty = DependencyProperty.Register("XProperty", typeof(Double), typeof(DiagramItem));
            YProperty = DependencyProperty.Register("YProperty", typeof(Double), typeof(DiagramItem));
            SelectedEvent = MultiSelector.SelectedEvent.AddOwner(typeof(DiagramItem));
            UnselectedEvent = MultiSelector.SelectedEvent.AddOwner(typeof(DiagramItem));
            IsSelectedProperty = MultiSelector.IsSelectedProperty.AddOwner(typeof(DiagramItem));

       }


       public Double X
       {
            get
            {
                return (Double)this.GetValue(XProperty);
            }

            set
            {
                this.SetValue(XProperty, value);
            }
       }

       public Double Y
       {
            get
            {
                return (Double)this.GetValue(YProperty);
            }
            set
            {
                 this.SetValue(YProperty, value);
            }
        }
    
        public Point Location
        {
            get
            {
                return new Point(X, Y);
            }

            set
            {
                this.X = value.X;
                this.Y = value.Y;
            }
        }

    }

神奇之处在于绑定的正确使用,关键是添加contentitem作为源。下一步显然是处理项的选择,但这本身就是另一个问题。

如果有帮助,我基于我的绘图和图解自定义控件写了一篇代码项目文章,名为NetworkView:


没问题!如果行UnselectedEvent=MultiSelector.SelectedEvent.AddOwner真的是UnselectedEvent=MultiSelector.UnselectedEvent.AddOwner,我很高兴能提供帮助?
    public class Diagram : MultiSelector
    {
        public Diagram()
        {
           this.CanSelectMultipleItems = true;


            // The canvas supports absolute positioning
            FrameworkElementFactory panel = new FrameworkElementFactory(typeof(Canvas)); 
            this.ItemsPanel = new ItemsPanelTemplate(panel);


            // Tells the container where to position the items
           this.ItemContainerStyle = new Style();
            this.ItemContainerStyle.Setters.Add(new Setter(Canvas.LeftProperty, new Binding("X")));
            this.ItemContainerStyle.Setters.Add(new Setter(Canvas.TopProperty, new Binding("Y")));
        }


        protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
        {
            FrameworkElement contentitem = element as FrameworkElement;

            Binding leftBinding = new Binding("XProperty");
            leftBinding.Source = contentitem;

            Binding topBinding = new Binding("YProperty");
            topBinding.Source = contentitem;

            contentitem.SetBinding(Canvas.LeftProperty, leftBinding);
            contentitem.SetBinding(Canvas.TopProperty, topBinding);
            base.PrepareContainerForItemOverride(element, item);
        }





 public class DiagramItem : ContentControl
 {
       public static readonly DependencyProperty XProperty;
       public static readonly DependencyProperty YProperty;
       public static readonly RoutedEvent SelectedEvent;
       public static readonly RoutedEvent UnselectedEvent;
       public static readonly DependencyProperty IsSelectedProperty;

       public DiagramItem()
       {
       }

       static DiagramItem()
       {
            XProperty = DependencyProperty.Register("XProperty", typeof(Double), typeof(DiagramItem));
            YProperty = DependencyProperty.Register("YProperty", typeof(Double), typeof(DiagramItem));
            SelectedEvent = MultiSelector.SelectedEvent.AddOwner(typeof(DiagramItem));
            UnselectedEvent = MultiSelector.SelectedEvent.AddOwner(typeof(DiagramItem));
            IsSelectedProperty = MultiSelector.IsSelectedProperty.AddOwner(typeof(DiagramItem));

       }


       public Double X
       {
            get
            {
                return (Double)this.GetValue(XProperty);
            }

            set
            {
                this.SetValue(XProperty, value);
            }
       }

       public Double Y
       {
            get
            {
                return (Double)this.GetValue(YProperty);
            }
            set
            {
                 this.SetValue(YProperty, value);
            }
        }
    
        public Point Location
        {
            get
            {
                return new Point(X, Y);
            }

            set
            {
                this.X = value.X;
                this.Y = value.Y;
            }
        }

    }