I'm trying to make a WPF UIElement
that does some special rendering.
The problem is that I can't get databinding to work for a PointCollection
. Inside OnRender()
of the GraphElement
, the Points property is null, which doesn't make any sense to me.
class GraphElement : UIElement
{
public static readonly DependencyProperty PointsProperty = DependencyProperty.Register(
"Points",
typeof(PointCollection),
typeof(GraphElement),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));
public PointCollection Points
{
get { return (PointCollection)GetValue(PointsProperty); }
set { SetValue(PointsProperty, value); }
}
protected override void OnRender(DrawingContext drawingContext)
{
base.OnRender(drawingContext);
//Points is null
Debug.Assert(Points != null);
}
}
class TestViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private PointCollection _viewModelPoints;
public PointCollection ViewModelPoints
{
get { return _viewModelPoints; }
set
{
_viewModelPoints = value;
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("ViewModelPoints"));
}
}
}
<Window x:Class="TestApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestApp"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Canvas>
<local:GraphElement Points="{Binding Path=ViewModelPoints}"/>
</Canvas>
</Grid>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace TestApp
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
var testViewModel = new TestViewModel();
testViewModel.ViewModelPoints = new PointCollection();
testViewModel.ViewModelPoints.Add(new Point(0.0, 0.0));
DataContext = testViewModel;
InitializeComponent();
}
}
}
Change the inheritance on GraphElement
from UIElement
to FrameworkElement
(which in turn inherits UIElement
). This is where you have the DataContext
dp etc.
class GraphElement : FrameworkElement
{
//...
}
Copied your code into a sample project (changing UIElement to FrameworkElement) and Points is not null in OnRender. Uploaded the project here.