wpf databound自定义控件 - 为什么对自定义控件未检测到数据源的更改?

问题描述:

我有一个自定义控件和视图模型对象。视图模型上的一个属性绑定到自定义控件上,我可以看到自定义控件实际上从视图模型对象接收了这个值 - 但是我的处理程序代码(GeometryText.Set)没有执行。我究竟做错了什么?!wpf databound自定义控件 - 为什么对自定义控件未检测到数据源的更改?

注意事件处理程序的自定义控件放置断点 - 如果我更改窗口的大小,我可以检查观察窗口中的GeometryText属性 - 它会在我期望的情况下。

感谢您的任何输入,

安德斯,丹麦

ComponentDrawing.xaml.cs

using System.ComponentModel; 
    using System.Windows; 
    using System.Windows.Controls; 
    using Rap1D.ServiceLayer.Interfaces.Services; 
    using StructureMap; 

    namespace Rap1D.Rap1D_WPF.Controls 
    { 
     /// <summary> 
     /// Interaction logic for ComponentDrawing.xaml 
     /// </summary> 
     public partial class ComponentDrawing 
     { 
      public static DependencyProperty GeometryTextProperty =DependencyProperty.Register("GeometryText", typeof (string), typeof (ComponentDrawing), new FrameworkPropertyMetadata 
                            (
                            "", 
                            FrameworkPropertyMetadataOptions 
                             . 
                             None)); 

      private Canvas _canvas; 


      public ComponentDrawing() 
      { 
       InitializeComponent(); 
      } 

      public string GeometryText 
      { 
       get { return ((string) GetValue(GeometryTextProperty)); } 


       set 
       { 
        SetValue(GeometryTextProperty, value); 
        ReadGeometryTextIntoDrawing(value); 
       } 
      } 

      private void ReadGeometryTextIntoDrawing(string fileText) 
      { 
       // Allow control to be visible at design time without errors shown. 
       // I.e. - don't execute code below at design time. 
       if (DesignerProperties.GetIsInDesignMode(this)) 
        return; 

       // OK - we are a running application 

       //if (_canvas != null) 
       // return; 

       // OK - this is first time (-ish) we are running 

       if (ActualWidth == 0) 
        return; 

       // We have a valid screen to pain on 

       var componentDrawingService = ObjectFactory.GetInstance<IComponentDrawingService>(); 

       //var commandTextProvider = ObjectFactory.GetInstance<ICommandTextProvider>(); 

       //var fileText = ((IViewModelBase) DataContext).GeometryText; 

       // If getting the file text fails for some reason, just abort to avoid further problems. 
       if (fileText == null) 
        return; 

       var pg = componentDrawingService.GetDrawings(fileText, 0, ActualWidth, 0, ActualHeight); 

       _canvas = new Canvas(); 

       foreach (var path in pg) 
       { 
        _canvas.Children.Add(path); 
       } 

       Content = _canvas; 
      } 

      private void UserControl_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) 
      { 
       //ReadGeometryTextIntoDrawing(); 
      } 

      private void UserControl_Loaded(object sender, RoutedEventArgs e) 
      { 
       //ReadGeometryTextIntoDrawing(); 
      } 

      private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e) 
      { 
       //ReadGeometryTextIntoDrawing(); 
      } 
     } 
    } 

ComponentDrawing.xaml:

<UserControl x:Class="Rap1D.Rap1D_WPF.Controls.ComponentDrawing" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300" 
       DataContextChanged="UserControl_DataContextChanged" Loaded="UserControl_Loaded" SizeChanged="UserControl_SizeChanged"> 
     <Grid Background="White"> 
      <Path Stroke="Black"></Path> 
     </Grid> 
    </UserControl> 

用法:

<Controls:RadPane x:Class="Rap1D.Rap1D_WPF.Controls.ProductComponentDetails" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:Controls="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Docking" xmlns:Controls1="clr-namespace:Rap1D.Rap1D_WPF.Controls" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300" Header="{Binding DisplayName}"> 
     <Controls1:ComponentDrawing GeometryText="{Binding GeometryText}" /> 
    </Controls:RadPane> 

(实施INotifyPropertyChanged的)视图模型对象:

using System; 
    using Microsoft.Practices.Prism.Events; 
    using Rap1D.ExternalInterfaceWrappers.Interfaces; 
    using Rap1D.ModelLayer.Interfaces.Adapters; 
    using Rap1D.ModelLayer.Interfaces.Structure; 
    using Rap1D.ServiceLayer.Interfaces.Adapters; 
    using Rap1D.ServiceLayer.Interfaces.Providers; 
    using Rap1D.ViewModelLayer.Interfaces; 

    namespace Rap1D.ViewModelLayer.Implementations 
    { 
     public class ProductComponentViewModel : TreeViewItemViewModel, IProductComponentViewModel 
     { 

     ... 

      public override string GeometryText 
      { 
       get 
       { 
        var pentaResponse = _commandTextProvider.GetCommandText(ProductComponent); 
        return DateTime.Now.ToString()+ pentaResponse.Payload; 
       } 
      } 

     ... 

} }

相关属性setter如果通过结合改变不被调用。如果你想以某种方式对依赖属性值反应改变要注册在属性元数据的回调:

http://msdn.microsoft.com/en-us/library/ms557294.aspx

类似的东西(不知道这是编译的,让我知道,如果事情是错误的):

public static DependencyProperty GeometryTextProperty = 
    DependencyProperty.Register(... , new FrameworkPropertyMetadata(GeometryTextCallback)); 

public static void GeometryTextCallback(DependencyObject source, DependencyPropertyChangedEventArgs e) 
{ 
    // cast source to your type and invoke method from your setter 
    ((ComponentDrawing)source)ReadGeometryTextIntoDrawing(value); 
} 
+0

FAN !!!! TASTIC!它解决了我的问题!你是我的(快速响应)英雄,今晚将被包括在我的床边祷告中! – 2011-02-08 19:56:26