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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24026193/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 11:50:09  来源:igfitidea点击:

Bind collection of lines to canvas in WPF

wpfdata-bindingbindingdrawingshapes

提问by SerG

I have an observable collection of line segments specified by its boundary points. How can I bind it to draw the lines on a canvas?

我有一个由其边界点指定的线段的可观察集合。如何绑定它以在画布上绘制线条?

I have seen the solutionfor shapes using only one point to define the position. But for applying this approach to lines it need awkward precomputations on coordinates to get the position of outer rectangle and make line coordinates relative to it. Is there a way to avoid it?

我已经看到了仅使用一个点来定义位置的形状解决方案。但是为了将这种方法应用于线,它需要对坐标进行笨拙的预计算以获得外部矩形的位置并相对于它制作线坐标。有没有办法避免它?

回答by

Here is an example how you could do it:

这是一个如何做到的示例:

The line is defined as follows:

该行定义如下:

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

    public Point To { get; set; }
}

MainWindow.xaml:

主窗口.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:

主窗口.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;
    }
}

In the above example, the lines are static, i.e. if you update the Fromand Topositions, the UI will not update. If you want the UI to update, you must implement INotifyPropertyChangedfor the Lineclass.

在上面的例子中,线条是静态的,即如果你更新FromTo位置,UI 将不会更新。如果您希望 UI 更新,则必须INotifyPropertyChangedLine该类实现。

This sample shows a window that looks like this:

此示例显示了一个如下所示的窗口:

screen shot

截屏

回答by sagneta

As an aside, what I often do to avoid the ItemsControlis to use PolyLine and simply bind a collection of points. In the XAML:

顺便说一句,为了避免ItemsControl,我经常做的是使用 PolyLine 并简单地绑定一组点。在 XAML 中:

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

Your code would simply be a PointCollection:

您的代码将只是一个 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;
    }
  }}

I find the ItemsControl will not work in some instances. Perhaps a defect in the WPF or something I don't understand. It is certainly more complicated than simple binds which can achieve the same results.

我发现 ItemsControl 在某些情况下不起作用。也许是 WPF 中的缺陷或我不明白的东西。它肯定比可以实现相同结果的简单绑定更复杂。

One thing to keep in mind is that you can't just add points to the already bound control and perform a NotifyPropertyChanged and expect it to work. You have to actually set an entirely new PointCollection. You can copy the old PointCollection to the new one via a constructor so it isn't much of a hassle.

要记住的一件事是,您不能只向已绑定的控件添加点并执行 NotifyPropertyChanged 并期望它起作用。您必须实际设置一个全新的 PointCollection。您可以通过构造函数将旧的 PointCollection 复制到新的 PointCollection 中,这样就不会很麻烦了。