改变多边形的顶点

3

解决方案 窗口拖动时动态边距

因此,我正在尝试使我的多边形随着窗口的移动而移动。我有以下内容;

    private void ResetPolygon(Point Point1, Point Point2, Point Point3)
    {
        SpeechPoly.Points.Clear();
        ObservableCollection<Point> myPointCollection = new ObservableCollection<Point>();
        myPointCollection.Add(Point3);
        myPointCollection.Add(Point2);
        myPointCollection.Add(Point1);
        foreach (Point p in myPointCollection)
        {
            SpeechPoly.Points.Add(p);
        }
    }

    private void Window_LocationChanged(object sender, EventArgs e)
    {
        if (this.IsLoaded)
        {
            Point Point1 = new Point(newPoint3);
            Point Point2 = new Point(newPoint2);
            Point Point3 = new Point(newPoint1);
            ResetPolygon(newPoint1, newPoint2, newPoint3);

//Write out the values of both the list and the polygon to screen!
            txtBlock.Text = newPoint1.X.ToString("N2") + ", " + newPoint1.Y.ToString("N2") + 
"\n" + newPoint2.X.ToString("N2") + ", " + newPoint2.Y.ToString("N2") + "\n" + 
newPoint3.X.ToString("N2") + ", " + newPoint3.Y.ToString("N2");

            txtBlock.Text += "\n" + SpeechPoly.Points[0].X.ToString("N2") + ", " + 
SpeechPoly.Points[0].Y.ToString("N2") + "\n" + SpeechPoly.Points[1].X.ToString("N2") + ", " +        
SpeechPoly.Points[1].Y.ToString("N2") + "\n" + SpeechPoly.Points[2].X.ToString("N2") + ", "+ 
SpeechPoly.Points[2].Y.ToString("N2");
                        }
                    }

但是无论如何,多边形的形状始终保持不变,即使明显显示了 List 中所有Points 的值,并且Polygon 的点明显在变化。

我还尝试将PolygonPoints 属性绑定到我的代码。

<Polygon
    Name="SpeechPoly"
    Points="{Binding myPointCollection, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
    Stroke="Black" 
    StrokeThickness="2"
    </Polygon>

我还尝试过使用pointsCollection而不是List<Points>,但结果相同。似乎Polygon没有刷新。
3个回答

3

之前的回答只是一种变通方法,我并不满意。

我找到了一个更好的解决方案,它不需要重置数据绑定。

因此,来自 XAML 的绑定将被导向具有 INCC 的属性,然而数据本身会被转换为点以便在绘制多边形时使用。

<Window x:Class="WpfApplication9.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication9"
    Title="MainWindow" Height="350" Width="525" LocationChanged="Window_LocationChanged" >
<Window.Resources>
    <local:MyPointCollectionConverter x:Key="mcolconv" />
</Window.Resources>
<Canvas>
    <Polygon Name="SpeechPoly" Stroke="Black" StrokeThickness="2" 
             Points="{Binding Path=myPointCollection, Converter={StaticResource mcolconv}}" />
</Canvas>

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;

namespace WpfApplication9
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private ObservableCollection<Point> _myPointCollection = new ObservableCollection<Point>();
    public ObservableCollection<Point> myPointCollection { get { return _myPointCollection; } }

    public MainWindow()
    {
        myPointCollection.Add(new Point(100, 50));
        myPointCollection.Add(new Point(150, 100));
        myPointCollection.Add(new Point(50, 100));
        InitializeComponent();
        DataContext = this;
    }

    private void ResetPolygon(Point Point1, Point Point2, Point Point3)
    {
        myPointCollection.Clear();
        myPointCollection.Add(Point1);
        myPointCollection.Add(Point2);
        myPointCollection.Add(Point3);
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs("myPointCollection"));
    }

    private void Window_LocationChanged(object sender, EventArgs e)
    {
        if (this.IsLoaded)
        {
            Random rnd = new Random();
            Point Point1 = new Point(rnd.Next(50, 200), rnd.Next(50, 200));
            Point Point2 = new Point(rnd.Next(50, 200), rnd.Next(50, 200));
            Point Point3 = new Point(rnd.Next(50, 200), rnd.Next(50, 200));
            ResetPolygon(Point1, Point2, Point3);
        }

    }
}

public class MyPointCollectionConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var regPtsColl = new PointCollection(); //regular points collection.
        var obsPtsColl = (ObservableCollection<Point>)value; //observable which is used to raise INCC event.
        foreach (var point in obsPtsColl)
            regPtsColl.Add(point);
        return regPtsColl;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return null;
    }

    #endregion
}
}

0
Window_LocationChanged处理程序中所做的是添加点,所以你最终会得到更多的多边形。你的myPointCollection必须是一个ObservableCollection,并且在添加点之前必须清除集合。我还想知道是否可以使用从Point(System.Windows.Point)继承的类,但重载x和y来NotifyingPropertyChanged它们,这样绑定就可以更新。如果它起作用了,你就不必再改变集合,而是改变集合内容。 更新后编辑: 看起来问题出在你的更新上:因为你使用相同的集合进行更新,所以没有更新发生。
这是完全正常的行为,因为集合(PointCollection)没有实现CollectionChanged,所以即使你清空它,clr也只能看到相同的对象,所以没有变化,因此没有更新。
你不应该修改(清空)Xaml多边形对象本身的点集合,因为绑定已经足够了。
  1. 尝试每次创建一个新的PointCollection,添加点,并将列表分配给多边形点。

  2. 或者尝试创建通知点并更改点。也许您可以使用空字符串""同时通知X和Y表示所有内容都已更改,或者使用"X"通知X,使用"Y"通知Y。


谢谢,那是一个非常明显的错误。但还是不对,请参见上面的更新。 - windowsgm
我更新了我的答案。你的集合是Observable Collection吗? - GameAlchemist
它实际上是一个PointCollection。http://msdn.microsoft.com/en-us/library/system.windows.media.pointcollection.aspx - windowsgm
我已经更新了我的答案并加入了这些信息。我想知道是否使用ObservableCollection(Of Points)并使用Clear()方法可以解决问题。 - GameAlchemist
嗨,文森特,很抱歉回复你有所延迟。我更新了我的问题。我尝试了你的第一个建议,但没有成功。你能给我一些关于第二个建议的示例代码吗?我有点不太清楚你要我做什么。 - windowsgm
实际上,我发现多边形确实在移动,但由于形状保持不变,它看起来并不像是在移动。我遇到的问题实际上是另一个问题,在这里我已经详细说明了,如果您想查看的话。如果您能帮我解决真正的问题,我可以从这个问题中给您提供悬赏!http://stackoverflow.com/questions/11327398/line-joining-parent-to-child-window - windowsgm

0

PointsCollection 没有使用 INotifyCollectionChanged 接口,因此绑定将永远不知道有什么变化。

您可以通过刷新绑定来解决此问题。

以下是一个示例,可以实现您所要求的功能:

<Window x:Class="WpfApplication9.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525" LocationChanged="Window_LocationChanged" >
<Canvas>
    <Polygon Name="SpeechPoly" Stroke="Black" StrokeThickness="2" Points="{Binding Path=myPointCollection}" />
</Canvas>

using System;
using System.Windows;
using System.Windows.Media;

namespace WpfApplication9
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public PointCollection myPointCollection { get; set; }

    public MainWindow()
    {
        myPointCollection = new PointCollection
        {
            new Point(100, 50),
            new Point(150, 100),
            new Point(50, 100)
        };
        InitializeComponent();
        DataContext = this;
    }

    private void ResetPolygon(Point Point1, Point Point2, Point Point3)
    {
        myPointCollection[0] = Point1;
        myPointCollection[1] = Point2;
        myPointCollection[2] = Point3;
        DataContext = null;
        DataContext = this;
    }

    private void Window_LocationChanged(object sender, EventArgs e)
    {
        if (this.IsLoaded)
        {
            Random rnd = new Random();
            Point Point1 = new Point(rnd.Next(50, 200), rnd.Next(50, 200));
            Point Point2 = new Point(rnd.Next(50, 200), rnd.Next(50, 200));
            Point Point3 = new Point(rnd.Next(50, 200), rnd.Next(50, 200));
            ResetPolygon(Point1, Point2, Point3);
        }

    }
}

}

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