有没有办法在XAML中绑定Point结构坐标?例如,我想创建一个三角形,其中的点数取决于控制宽度和高度。
<Polygon>
<Polygon.Points>
<Point X="{Binding ElementName=control, Path=ActualWidth}" Y="{Binding ElementName=control, Path=ActualHeight}"/>
</Polygon.Points>
</Polygon>
错误:
A&#39;绑定&#39;不能设置在&#39; X&#39;类型的属性&#39; Point&#39;。 A&#39;绑定&#39;只能在DependencyObject的DependencyProperty上设置。
我无法使用继承,因为Point类型是一种结构。我试图创建PointCollection属性绑定,但它不能很好地工作。
答案 0 :(得分:3)
你去吧
我尝试用两种方法解决三角形
结果
Viewbox方法
如果您有兴趣渲染一个控件大小的三角形,那么这可能是您的选择
<Grid>
<Viewbox Stretch="Fill">
<Path Data="M 1.5,0 L 3,3 0,3 Z"
Width="3" Height="3"
Fill="Gray" />
</Viewbox>
</Grid>
上述方法将渲染一个三角形,并通过Viewbox调整为父控件的大小,另外您可以根据需要添加旋转变换到路径并旋转三角形。
如果您只需要一个三角形
,建议采用这种方法使用转换器的多边形
<Grid xmlns:l="clr-namespace:CSharpWPF"
x:Name="control">
<Grid.Resources>
<l:ElementToTrianglePointsConverter x:Key="ElementToTrianglePointsConverter" />
</Grid.Resources>
<Polygon Points="{Binding ElementName=control, Converter={StaticResource ElementToTrianglePointsConverter}}"
FillRule="Nonzero"
Fill="Gray" />
</Grid>
转换器
namespace CSharpWPF
{
public class ElementToTrianglePointsConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
FrameworkElement element = value as FrameworkElement;
PointCollection points = new PointCollection();
Action fillPoints = () =>
{
points.Clear();
points.Add(new Point(element.ActualWidth / 2, 0));
points.Add(new Point(element.ActualWidth, element.ActualHeight));
points.Add(new Point(0, element.ActualHeight));
};
fillPoints();
element.SizeChanged += (s, ee) => fillPoints();
return points;// store;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
上面的方法是小马车,我总是要在看到三角形之前重新调整窗口大小。我可以在设计时默认看到它,但不能在运行时看到它,除非我调整窗口大小。虽然多边形中有点但没有渲染,不知道为什么?需要调查问题
答案 1 :(得分:2)
你可以使用MultiBinding和转换器。
可能如下所示:
<Window x:Class="WpfApplication13.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local ="clr-namespace:WpfApplication13"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:converter x:Key="pointConverter" />
</Window.Resources>
<Grid x:Name="control" >
<Polygon Fill="Black" Stroke="Black">
<Polygon.Points>
<MultiBinding Converter="{StaticResource pointConverter}" >
<Binding Path="ActualWidth" ElementName="control"/>
<Binding Path="ActualHeight" ElementName="control"/>
</MultiBinding>
</Polygon.Points>
</Polygon>
</Grid>
</Window>
或者您可以在后台执行此操作:
public MainWindow()
{
InitializeComponent();
MultiBinding mb = new MultiBinding();
Binding bind = new Binding("ActualWidth");
bind.Source = control;
mb.Bindings.Add(bind);
bind = new Binding("ActualHeight");
bind.Source = control;
mb.Bindings.Add(bind);
mb.Converter = new converter();
pg.SetBinding(Polygon.PointsProperty, mb);
}
class converter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
try
{
double width = (double)values[0];
double height = (double)values[1];
PointCollection pc = new PointCollection();
pc.Add(new Point(0, 0));
pc.Add(new Point(width - 10, height - 10));
return pc;
}
catch
{
return null;
}
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
答案 2 :(得分:0)
我刚刚解决了我的问题。我使用@pushpraj解决方案的想法,但我将ActualWidth和ActualHeight更改为Width和Height,所以我的转换器类现在看起来像这样:
namespace CSharpWPF
{
public class ElementToTrianglePointsConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
FrameworkElement element = value as FrameworkElement;
PointCollection points = new PointCollection();
Action fillPoints = () =>
{
points.Clear();
points.Add(new Point(element.Width / 2, 0));
points.Add(new Point(element.Width, element.Height));
points.Add(new Point(0, element.Height));
};
fillPoints();
element.SizeChanged += (s, ee) => fillPoints();
return points;// store;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
我认为在初始化所有子控件时初始化ActualWidth和ActualHeight属性。
感谢您的帮助。