我正在尝试在C#/ WPF中创建一个图表应用程序。我想要的有点类似于Microsoft Visio,虽然我不想克隆它。我正在编写这个问题,因为我正在编码,只是把我遇到的所有问题都放进去,以防有人发现它有用。也许我一直在想太难,但我觉得我可以把键盘放到键盘上并生成更好的代码,所以请随意对你抓到的每一个细节提出任何建议(语法不包括: - ))
简而言之:
为什么所有项目都位于(0,0)?
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("X");
Binding topBinding = new Binding("Y");
contentitem.SetBinding(Canvas.LeftProperty, leftBinding);
contentitem.SetBinding(Canvas.TopProperty, topBinding);
base.PrepareContainerForItemOverride(element, item);
}
public class DiagramItem : ContentControl
{
private Point _location;
public DiagramItem()
{
}
static DiagramItem()
{
}
public Point Location
{
get { return _location; }
set
{
_location = value;
}
}
public double X
{
get { return _location.X; }
set
{
_location.X = value;
}
}
public double Y
{
get { return _location.Y; }
set
{
_location.Y = value;
}
}
}
//...
好的,所以我的想法是 Diagram:ItemsControl 将其项放置在Canvas面板上Item ItemItem.Location中定义的位置。 IOW当我在DiagramItem中更改X属性时,Diagram会在x轴上移动项目。
注意: MultiSelector派生自ItemsControl和Selector,仅在此使用,因为我需要显示的项目可供选择。
请注意,如果可能,我不想使用xaml。
长期:
用户看到的Diagram实例具有以下要求:
我基本上有两个,可能还有三个与这个问题相关的课程。
Diagram.ItemsPanel又称显示项目的可视面板应该是支持绝对定位的面板,如画布。
我应该如何实现从MultiSelector派生的类,以及您可以指出哪些资源与此问题相关?
实现自定义MultiSelector / ItemsControl时需要考虑什么?
资源:
我发现很少有与我的问题相关的资源,但是我再也不确定我应该寻找什么。我已经使用Reflector读取了ListBox和ListBoxItem的源代码,但没有发现它非常有用。
其他资源:
答案 0 :(得分:6)
好的,显然这可以通过使用绑定和属性框架轻松实现。
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;
}
}
}
魔术是正确使用Bingings,关键是将contentitem添加为Source。下一步显然是处理项目的选择,但这是另一个问题。
答案 1 :(得分:1)
如果有任何帮助,我根据我的图形和图表自定义控件编写了一个代码项目文章,名为NetworkView:
http://www.codeproject.com/Articles/182683/NetworkView-A-WPF-custom-control-for-visualizing-a