C# 如何在WPF/C中创建自定义MultiSelector/ItemsControl
我正在尝试用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的源代码,但没有发现它非常有用 其他资源: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中定义的位置。当我改变图表项
好的,显然这可以通过使用绑定和属性框架轻松实现
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;
}
}
}