解 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
清楚地显示Points
和List
中所有Polygon
的值,多边形仍保持相同的形状。积分肯定在变化。
我还尝试将Points
的{{1}}属性绑定到我的代码。
Polygon
我也尝试使用<Polygon
Name="SpeechPoly"
Points="{Binding myPointCollection, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
Stroke="Black"
StrokeThickness="2"
</Polygon>
而不是pointsCollection
但结果相同。几乎看起来List<Points>
并不令人耳目一新。
答案 0 :(得分: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
}
}
答案 1 :(得分:0)
你在Window_LocationChanged
处理程序中所做的就是添加点,所以难怪你最终得到更多的多边形。您的myPointCollection
必须是ObservableCollection
,您必须在添加积分之前清除收藏。我还想知道你是否可以使用继承自Point
(System.Windows.Point
)但是将x和y重载到NotifyingPropertyChanged
的类,以便绑定可以更新。如果它有效,则不必再更改集合,而是集合内容。
更新后修改:
看起来问题在于您的更新:因为您使用相同的集合更新它,所以不会发生更新
这是完全正常的行为,因为Collection(a PointCollection
)没有实现CollectionChanged
,所以即使你清除它,clr'看到'的所有东西都是同一个对象,所以没有变化,因此没有更新
你不应该修改(清除)Xaml Polygon对象本身的点集合,因为绑定就足够了。
每次尝试创建新的PointCollection
,添加点,并将列表分配给多边形点。
或尝试制作通知点并更改积分。也许你可以用空字符串“”通知X和Y,这意味着一切都改变了,或者用“X”通知X,用“Y”通知Y.
答案 2 :(得分: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);
}
}
}
}