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

时间:2011-02-08 19:27:11

标签: wpf data-binding custom-controls

我有自定义控件和视图模型对象。视图模型上的属性绑定到自定义控件,我可以看到自定义控件实际上从视图模型对象接收vaule - 但我的处理程序代码(GeometryText.Set)未执行。我做错了什么?!

注意自定义控件上的事件处理程序我放置了断点 - 如果我改变了窗口的大小,我可以检查监视窗口中的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;
                }
            }

        ...

}         }

1 个答案:

答案 0 :(得分:5)

如果通过绑定更改,则不会调用依赖项属性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);
}