自定义类型的内部属性更改时,不会触发依赖属性属性更改回调

时间:2014-01-25 09:42:11

标签: c# wpf

现在这是一个令人困惑的标题...也许我可以更详细地解释:我有一个名为ChartTheme的自定义类型的依赖属性:

public NewChartTheme ChartTheme
{
    get
    {
        return (NewChartTheme)GetValue(ChartThemeProperty);
    }
    set
    { 
        SetValue(ChartThemeProperty, value);
    }
}

public static readonly DependencyProperty ChartThemeProperty = DependencyProperty.Register
                                     (
                                      "ChartTheme",
                                      typeof(NewChartTheme),
                                      typeof(RadChartViewUserControlView),
                                      new FrameworkPropertyMetadata() 
                                          { PropertyChangedCallback = UpdateChartingTheme }
                                     );

在自定义类型NewChartTheme中,有许多属性。基本上,我希望只要其中一个属性发生更改,就会触发DP回调。我认为回调函数会触发,因为只要其中一个属性发生变化,对象本身就会发生变化,但显然情况并非如此。

有关如何将此属性更改为冒泡的任何建议?

修改

关于Rohit Vats的回答,我实施了他的代码,但有一点需要注意。 NewChartTheme是MVVM模式中的模型。因此,它没有实现INPC。我公开了ViewModel(通过基类实现INPC)并相应地修改了代码。这有点hackish,但我认为它应该工作。但是,在VM中更改属性时,MainWindow_PropertyChanged方法永远不会被命中。这是我改变的代码:

private static void UpdateChartingTheme(DependencyObject sender,
                                    DependencyPropertyChangedEventArgs args)
{
    IUserInteractionService iuis =
        AllianceApp.Container.GetExportedValue<IUserInteractionService>();
    NewChartTheme ct = (sender as RadChartViewUserControlView).ChartTheme;
    NewChartThemeViewModel vm = (sender as RadChartViewUserControlView).ChartThemeVM;

    if (args != null && args.Property != null && sender != null && ct != null)
    {
        vm = new NewChartThemeViewModel(iuis, ct);

        if (args.OldValue != null)
        {
            ((INotifyPropertyChanged)vm).PropertyChanged -=
                                                  MainWindow_PropertyChanged;
        }
        if (args.NewValue != null)
        {
            ((INotifyPropertyChanged)vm).PropertyChanged +=
                                                  MainWindow_PropertyChanged;
        }
    }
}

public static void MainWindow_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    RadChartViewUserControlView chartView = sender as RadChartViewUserControlView;
    if (chartView.ChartTheme != null && chartView.Data != null)
        chartView.Create2DCharting(chartView);
}

我很尴尬地说,过去一天我已经阅读了这个主题,但我不知道为什么这段代码不起作用。

编辑2

我的最终代码非常感谢Rohit Vats。非常感谢:

private static void UpdateChartingTheme(DependencyObject sender, 
                                        DependencyPropertyChangedEventArgs args)
{
    if (args.OldValue != null)
    {
        ((INotifyPropertyChanged)args.OldValue).PropertyChanged += (sender1, args1) => MainWindow_PropertyChanged(sender1, args1, sender as RadChartViewUserControlView);
    }

    if (args.NewValue != null)
    {
        ((INotifyPropertyChanged)args.NewValue).PropertyChanged += 
            (sender1, args1) => 
                MainWindow_PropertyChanged(sender1, args1, sender as RadChartViewUserControlView);
    }
}        

static void MainWindow_PropertyChanged(object sender, PropertyChangedEventArgs e, RadChartViewUserControlView userControl)
{
    if (userControl != null && userControl.Data != null)
        userControl.Create2DCharting(userControl);
}

1 个答案:

答案 0 :(得分:2)

正如您在评论中提到的那样,除非为依赖属性更改属性 ,否则不会调用 回调。

但无论如何,有一种方法可以通过以下步骤实现这一目标:

  • 当第一次为此DP设置值时,您可以挂钩PropertyChanged类NewChartTheme 的事件(假设您已在此类上实现了INPC并在任何时候提升了PropertyChanged事件财产改变了。)

  • 将您的代码放在PropertyChanged处理程序中,您就可以了。

  • 同时确保,当实际DP更改为某个其他实例时取消挂起PropertyChanged事件(只是为了避免任何内存泄漏)

这里所说的是我在上面提到的代码:

private static void UpdateChartingTheme(DependencyObject sender, 
                                        DependencyPropertyChangedEventArgs args)
{
   if (args.OldValue != null)
   {
       ((INotifyPropertyChanged)args.OldValue).PropertyChanged -= 
                                             MainWindow_PropertyChanged;
   }
   if (args.NewValue != null)
   {
       ((INotifyPropertyChanged)args.NewValue).PropertyChanged += 
                                            MainWindow_PropertyChanged;
   }
}

static void MainWindow_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    // Do your work here.
}