ChandlerPelhams
ChandlerPelhams

Reputation: 1678

Caliburn.Micro and custom dependency properties not working

I am using the Caliburn.Micro framework for building my application. I am trying to create a custom chart control derived from the WPF toolkit chart, which needs to have 2 custom dependency properties added to it.

For some reason, Caliburn.Micro is not binding correctly to the DP's that I created, but is working fine for existing ones. Is there something that I need to do for CM to recognize these additional properties?

(In my example, the binding Title="{Binding ChartSeriesType}" works correctly. The ChartData and ChartType are not being updated.)

SampleChart.xaml.cs

public partial class SampleChart : Chart
{
    public ChartSeriesType ChartType
    {
        get { return (ChartSeriesType)GetValue(ChartTypeProperty); }
        set
        {
            SetValue(ChartTypeProperty, value);
            dataChaged();
        }
    }

    // Using a DependencyProperty as the backing store for ChartType.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ChartTypeProperty =
        DependencyProperty.Register("ChartType", typeof(ChartSeriesType), typeof(SampleChart), new UIPropertyMetadata(null));


    public AgilityTableBase ChartData
    {
        get { return (AgilityTableBase)GetValue(ChartDataProperty); }
        set
        {
            SetValue(ChartDataProperty, value);
            dataChaged();
        }
    }

    // Using a DependencyProperty as the backing store for ChartData.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ChartDataProperty =
        DependencyProperty.Register("ChartData", typeof(AgilityTableBase), typeof(SampleChart), new UIPropertyMetadata(null));

    private void dataChaged()
    {
        Console.WriteLine("data changed");
    } 
}

SampleChartView.xaml:

<UserControl x:Class="Agility.Presentation.ReportViewing.SampleChartView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:cal="http://www.caliburnproject.org"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:local="clr-namespace:Agility.Presentation.ReportViewing"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" d:DesignHeight="300"
         d:DesignWidth="300" mc:Ignorable="d">
<local:SampleChart Title="{Binding ChartSeriesType}" ChartData="{Binding ReportTable}" ChartType="{Binding ChartSeriesType}" />

SampleChartViewModel.cs:

public class SampleChartViewModel : PropertyChangedBase
{
    private ChartSeriesType _chartType;
    private SampleTableBase _reportTable;

    public SampleChartViewModel(SampleTableBase reportTable)
    {
        _reportTable = reportTable;
    }

    public SampleTableBase ReportTable
    {
        get { return _reportTable; }
        set
        {
            _reportTable = value;
            this.NotifyOfPropertyChange(() => ReportTable);
        }
    }

    public ChartSeriesType ChartSeriesType
    {
        get { return _chartType; }
        set
        {
            _chartType = value;
            this.NotifyOfPropertyChange(() => ChartSeriesType);
        }
    }
}

EDIT

The correct way to register the ChartType DependencyProperty is:

// Using a DependencyProperty as the backing store for ChartType.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ChartTypeProperty =
        DependencyProperty.Register("ChartType", typeof(ChartSeriesType), typeof(AgilityChart), new UIPropertyMetadata(ChartSeriesType.Bar
            , new PropertyChangedCallback(dataChanged)));

    private static void dataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Console.WriteLine("data changed");
    } 

Now, the dataChanged() method is being called.

Upvotes: 1

Views: 1748

Answers (1)

Rafal
Rafal

Reputation: 12619

One mistake I see in your code is that you add dataChaged() call to your property setter. This setter is only a convenience for you. It wont be called by binding. To react to dependency property change set callback delegate in UIPropertyMetadata that you pass while registering dp.

Moreover first argument of UIPropertyMetadata constructor is default value of property and ChartSeriesType looks like an enum so null in not appropriate default.

Next thing is that the dp owner type is set to AgilityChart and should be SampleChart, because that is your class name.

Upvotes: 2

Related Questions