【问题标题】:Changing a Polygon's Points更改多边形的点
【发布时间】:2012-07-01 02:41:21
【问题描述】:

解决方案 Dynamic Margin on Window Drag

所以我试图让我的多边形随着窗口的移动而移动。我有;

    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");
                        }
                    }

但是多边形无论如何都保持相同的形状,尽管Textblock 清楚地显示了List 中所有Points 的值,并且Polygon 的点肯定在变化。

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

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

我也尝试过使用pointsCollection 而不是List&lt;Points&gt;,但结果相同。几乎看起来Polygon 没有刷新。

【问题讨论】:

    标签: c# wpf data-binding polygon point


    【解决方案1】:

    你在Window_LocationChanged 处理程序中所做的就是添加点,所以难怪你最终会得到更多的多边形。您的myPointCollection 必须是ObservableCollection,并且您必须在添加积分之前清除集合。我还想知道您是否可以使用继承自 Point (System.Windows.Point) 的类,但将 x 和 y 重载到 NotifyingPropertyChanged 以便绑定可以更新。如果可行,您不必再更改 Collection,只需更改 Collection 内容即可。

    更新后编辑:

    看起来问题出在您的更新中:因为您使用相同的集合更新它,所以不会发生更新。
    这是完全正常的行为,因为集合(PointCollection)没有实现CollectionChanged,所以即使你清除它,所有 clr '看到'都是同一个对象,所以没有变化,因此没有更新。

    您不应该修改(清除)Xaml Polygon 对象本身的点集合,因为绑定就足够了。

    1. 尝试每次创建一个新的PointCollection,添加点,并将列表分配给多边形点。

    2. 或尝试制作通知点并更改点。也许你可以用空字符串“”通知 X 和 Y,这意味着一切都改变了,或者用“X”通知 X,用“Y”通知 Y。

    【讨论】:

    • 感谢这是一个如此明显的错误。但仍然不正确,请参阅上面的更新。
    • 我更新了我的答案。你的 Collection 是 Observable 的集合吗?
    • 其实是PointCollectionmsdn.microsoft.com/en-us/library/…
    • 我已经用这些信息更新了我的答案。我想知道使用 ObservableCollection(Of Points) 是否可以解决问题,使用 Clear()。
    • 您好文森特,很抱歉延迟回复您。更新了我的问题。尝试了您的建议1,但没有运气。你能给我一些2的示例代码吗?你让我做什么有点模糊。
    【解决方案2】:

    我对之前给出的答案并不满意,因为它毕竟是一种解决方法..

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

    因此,来自 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
    }
    }
    

    【讨论】:

      【解决方案3】:

      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);
              }
      
          }
      }
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-10-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-13
        • 2011-12-19
        • 2010-10-28
        相关资源
        最近更新 更多