在XAML中绑定多边形点

时间:2014-07-16 00:13:31

标签: c# wpf xaml binding

有没有办法在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属性绑定,但它不能很好地工作。

3 个答案:

答案 0 :(得分:3)

你去吧

我尝试用两种方法解决三角形

结果

result


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属性。

感谢您的帮助。