How do I bind a Polygon to an existing PointCollection in WPF?

EdwinG picture EdwinG · Nov 26, 2012 · Viewed 7k times · Source

My current implementation doesn't show anything on the form even though the collections I thought bounded have data (I checked in debug).

Here's some code:

    public event PropertyChangedEventHandler PropertyChanged;
    PointCollection imagePoints;
    public PointCollection ImagePoints
    {
        get
        {
            return this.imagePoints;
        }
        set
        {
            if (this.imagePoints != value)
            {
                this.imagePoints = value;
                if (this.PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("ImagePoints"));
                }
            }
        }
    }

and the corresponding xaml:

<Polygon x:Name="imagePolygon" Points="{Binding ImagePoints}" Stretch="Fill" Fill="Black" Opacity="0.8" />

Now, I did all the binding by writing the code. In this example, it works just fine, yet in mine, the points don't show up on the polygon.

Any pearls of wisdom?

Edit:here's the complete xaml code

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="WpfApplication2.HistogramWindow"
    Title="HistogramWindow" Height="436" Width="604">
<Grid>
    <TabControl HorizontalAlignment="Left" Height="406" VerticalAlignment="Top" Width="596" >
        <TabItem x:Name="imageTab" Header="Full Image" Height="23" VerticalAlignment="Top">
            <Border BorderBrush="Black" BorderThickness="1" Margin="10">
                <Polygon x:Name="imagePolygon" Points="{Binding ImagePoints}" Stretch="Fill" Fill="Black" Opacity="0.8" />
            </Border>
        </TabItem>
        <TabItem x:Name="boneTab" Header="Bone">
            <Border BorderBrush="Black" BorderThickness="1" Margin="10">
                <Border.BindingGroup>
                    <BindingGroup/>
                </Border.BindingGroup>
                <Polygon x:Name="bonePolygon" Points="{Binding BonePoints}" Stretch="Fill" Fill="Black" Opacity="0.8" >

                </Polygon>
            </Border>
        </TabItem>
        <TabItem x:Name="fatTab" Header="Fat" HorizontalAlignment="Left" Height="20" VerticalAlignment="Top" Width="57">
            <Border BorderBrush="Black" BorderThickness="1" Margin="10">
                <Polygon x:Name="fatPolygon" Points="{Binding FatPoints}" Stretch="Fill" Fill="Black" Opacity="0.8" />
            </Border>
        </TabItem>
    </TabControl>

</Grid>

Edit: After a modification of the config file, I find this in the output window:

System.Windows.Data Information: 41 : BindingExpression path error: 'ImagePoints'   property not found for 'object' because data item is null.  This could happen because the data provider has not produced any data yet. BindingExpression:Path=ImagePoints; DataItem=null; target element is 'Polygon' (Name='imagePolygon'); target property is 'Points' (type 'PointCollection')
System.Windows.Data Information: 20 : BindingExpression cannot retrieve value due to missing information. BindingExpression:Path=ImagePoints; DataItem=null; target element is 'Polygon' (Name='imagePolygon'); target property is 'Points' (type 'PointCollection')
System.Windows.Data Information: 21 : BindingExpression cannot retrieve value from null data item. This could happen when binding is detached or when binding to a Nullable type that has no value. BindingExpression:Path=ImagePoints; DataItem=null; target element is 'Polygon' (Name='imagePolygon'); target property is 'Points' (type 'PointCollection')
System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=ImagePoints; DataItem=null; target element is 'Polygon' (Name='imagePolygon'); target property is 'Points' (type 'PointCollection')

Answer

Peter Hansen picture Peter Hansen · Nov 26, 2012

I'm not sure why you are getting binding errors, but on first sight the code you have looks fine.

I have written a small piece of code that works, so you can check that out and see if you have missed something. I guess it must be kinda similar to yours..

Relevant part of the XAML:

<TabItem x:Name="imageTab" Header="Full Image" Height="23" VerticalAlignment="Top">
    <Border BorderBrush="Black" BorderThickness="1" Margin="10">
        <StackPanel>
            <Polygon x:Name="imagePolygon" Points="{Binding ImagePoints}" Stretch="Fill" Fill="Black" Opacity="0.8" />
            <Button Content="Set new points" Click="btnSetNew" />
        </StackPanel>
    </Border>
</TabItem>

Code-behind for the window:

public partial class Window1 : Window, INotifyPropertyChanged
{
    public Window1()
    {
        InitializeComponent();

        this.ImagePoints = new PointCollection
            (new [] { new Point(1, 2), new Point(34, 12), new Point(12, 99) });

        //Important - maybe you missed this?
        this.DataContext = this;
    }

    public event PropertyChangedEventHandler PropertyChanged;
    PointCollection imagePoints;
    public PointCollection ImagePoints
    {
        get
        {
            return this.imagePoints;
        }
        set
        {
            if (this.imagePoints != value)
            {
                this.imagePoints = value;
                if (this.PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("ImagePoints"));
                }
            }
        }
    }

    private void btnSetNew(object sender, RoutedEventArgs e)
    {
        this.ImagePoints = new PointCollection(
            new[] { new Point(23, 2), new Point(12, 556), new Point(4, 89) });
    }
}