将线条集合绑定到WPF画布中

7
我有一个由边界点指定的可观察线段集合。如何将其绑定以在画布上绘制线条?
我已经看到了仅使用一个点定义位置的形状的solution。但是,如果将这种方法应用于线条,则需要对坐标进行笨拙的预计算,以获取外部矩形的位置,并使线条坐标相对于它。有没有办法避免这种情况?

你能分享一下你尝试过的内容以及在坐标预计算方面的策略吗?这样我们就可以看一下。 - pushpraj
请查看此链接:http://stackoverflow.com/questions/15426460/bind-an-observablecollection-to-lines - voddy
2个回答

18

这里是一个示例,说明如何实现它:

该行定义如下:

public class Line
{
    public Point From { get; set; }

    public Point To { get; set; }
}

MainWindow.xaml:

<Window x:Class="WpfApplication20.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="300" Width="300">
    <ItemsControl ItemsSource="{Binding Lines}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Line X1="{Binding From.X}" Y1="{Binding From.Y}"
                      X2="{Binding To.X}" Y2="{Binding To.Y}"
                      Stroke="DarkGray" StrokeThickness="3"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Window>

MainWindow.xaml.cs:

public partial class MainWindow : Window
{
    public ObservableCollection<Line> Lines { get; private set; }

    public MainWindow()
    {
        Lines = new ObservableCollection<Line>
        {
            new Line { From = new Point(100, 20), To = new Point(180, 180) },
            new Line { From = new Point(180, 180), To = new Point(20, 180) },
            new Line { From = new Point(20, 180), To = new Point(100, 20) },
            new Line { From = new Point(20, 50), To = new Point(180, 150) }
        };

        InitializeComponent();
        DataContext = this;
    }
}

在上面的例子中,这些线条是静态的,即如果您更新FromTo的位置,则UI不会更新。如果要使UI更新,必须为Line类实现INotifyPropertyChanged
此示例显示的窗口如下所示:

screen shot


它能工作!但是如果ItemsControl将每个ItemTemplat'ed对象都包装到自己的容器中,那么这是怎么可能的呢?为什么这些链接答案需要这些解决方法? - SerG
1
我认为关键点在于所有容器都具有 Canvas.Top=0Canvas.Left=0,即它们都对齐到相同的原点。 - user128300
1
可能这只适用于行,因为它需要在元素内指定X和Y,而不是将整个对象从父边界移动,因为只有画布允许子内容的绝对定位,并且在ContentPresenter中是不可能的。 - SerG

2

顺便说一下,我通常为了避免使用ItemsControl而使用PolyLine,并简单地绑定一个点集合。在XAML中:

 <Polyline Points="{Binding Points}" Stroke="White" StrokeThickness=".1" />

您的代码将仅是一个点集合(PointCollection):
namespace YourNameSpace.ViewModels
{
class MainViewModel : ViewModelBase
{

    #region Parameters
    private PointCollection points = new PointCollection();
    public PointCollection Points
    {
        get { return points; }
        set
        {
            points = value;
            NotifyPropertyChanged("Points");
        }
    }

   public MainViewModel()
    {


        PointCollection polygonPoints = new PointCollection
        {
             new Point(10, 50),
             new Point(100, 50),
             new Point(50, 30),
             new Point(75, 100),
             new Point(75, 10)
        };

        this.Points = polygonPoints;
    }
  }}

我发现在某些情况下,ItemsControl可能无法正常工作。也许是WPF的缺陷或者我不理解的东西。它肯定比简单的绑定更加复杂,尽管可以实现相同的结果。
需要记住的一件事是,你不能仅仅添加点到已绑定的控件并执行NotifyPropertyChanged,然后期望它能够工作。你必须实际上设置一个全新的PointCollection。你可以通过构造函数将旧的PointCollection复制到新的PointCollection中,这样并不麻烦。

现在我已经不在这个问题的上下文中了(已经三年没有使用WPF了),无法评估您的解决方案,但希望它对其他人有用。 - SerG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接