【问题标题】:Silverlight: How to receive notification of a change in an inherited DependencyPropertySilverlight:如何接收继承的 DependencyProperty 更改的通知
【发布时间】:2009-05-07 14:21:08
【问题描述】:

我有一个继承自(你猜对了)Control 的控件。 我想在FontSizeStyle 属性发生更改时收到通知。在 WPF 中,我会通过调用 DependencyProperty.OverrideMetadata() 来做到这一点。当然,像这样有用的东西在 Silverlight 中没有位置。那么,一个人怎么会收到这些通知呢?

【问题讨论】:

    标签: silverlight dependency-properties


    【解决方案1】:

    我认为这是一个更好的方法。还是得看利弊。

     /// Listen for change of the dependency property
        public void RegisterForNotification(string propertyName, FrameworkElement element, PropertyChangedCallback callback)
        {
    
            //Bind to a depedency property
            Binding b = new Binding(propertyName) { Source = element };
            var prop = System.Windows.DependencyProperty.RegisterAttached(
                "ListenAttached"+propertyName,
                typeof(object),
                typeof(UserControl),
                new System.Windows.PropertyMetadata(callback));
    
            element.SetBinding(prop, b);
        }
    

    现在,您可以调用 RegisterForNotification 来注册元素属性的更改通知,例如。

    RegisterForNotification("Text", this.txtMain,(d,e)=>MessageBox.Show("Text changed"));
    RegisterForNotification("Value", this.sliderMain, (d, e) => MessageBox.Show("Value changed"));
    

    在同一http://amazedsaint.blogspot.com/2009/12/silverlight-listening-to-dependency.html上查看我的帖子

    使用 Silverlight 4.0 测试版。

    【讨论】:

    • 我喜欢这是一种更好的方式来包装丑陋的绑定,但这是获取属性更改通知的一种非常繁重的方式。
    • 只要我们需要完全从代码中完成,我想在我们从 MS 获得 Silverlight 中的 DependencyPropertyDescriptor 之前我们没有其他选择
    • 我也使用过这种方法,不幸的是它会泄漏内存。以我的经验,它将引用您使用它的任何元素,这反过来又会保留其他对象。罪魁祸首似乎是回调,它将在您的应用程序的生命周期中保留对您的视图的引用。
    • 它可以工作(+1!),但正如 Ian 所说,它不是最佳的。作为一种解决方法,我已将附加属性(在我的情况下称为 ListenAttachedIsEnabledProperty 移动到我想要覆盖的类中,并在构造函数 var b = new Binding("IsEnabled") { Source = this }; SetBinding(ListenAttachedIsEnabledProperty, b); 中添加了以下两行
    • 它会在为多个文本框调用 RegisterForNotification 时抛出,可能是因为您无法创建多个具有相同名称的 DependencyProperties。
    【解决方案2】:

    这是一个相当恶心的 hack,但你可以使用双向绑定来模拟它。

    即有类似的东西:

    public class FontSizeListener {
        public double FontSize {
            get { return fontSize; }
            set { fontSize = value; OnFontSizeChanged (this, EventArgs.Empty); }
        }
    
        public event EventHandler FontSizeChanged;
    
        void OnFontSizeChanged (object sender, EventArgs e) {
          if (FontSizeChanged != null) FontSizeChanged (sender, e);
        }
    }
    

    然后像这样创建绑定:

    <Canvas>
      <Canvas.Resources>
         <FontSizeListener x:Key="listener" />
      </Canvas.Resources>
    
      <MyControlSubclass FontSize="{Binding Mode=TwoWay, Source={StaticResource listener}, Path=FontSize}" />
    </Canvas>
    

    然后在您的控件子类中连接到侦听器的事件。

    【讨论】:

    • 当MyControlSubclass FontSize 属性发生变化时,绑定会清晰,所以看起来不起作用?不是吗?
    【解决方案3】:

    你不能从外部监听依赖属性改变的通知。

    您可以使用以下代码行访问依赖属性元数据:

    PropertyMetadata metaData = Control.ActualHeightProperty.GetMetadata(typeof(Control));
    

    但是,唯一公开的公共成员是“DefaultValue”。

    在 WPF 中有多种方法可以做到这一点。但 Silverlight 2 或 3 目前不支持它们。

    【讨论】:

      【解决方案4】:

      我看到的唯一解决方案是监听 LayoutUpdated 事件 - 是的,我知道它被调用了很多。但请注意,在某些情况下,即使 FontSize 或 Style 已更改,它也不会被调用。

      【讨论】:

        【解决方案5】:

        这是我一直使用的(虽然没有在 SL 上测试过,只是在 WPF 上测试过):

            /// <summary>
            /// This method registers a callback on a dependency object to be called
            /// when the value of the DP changes.
            /// </summary>
            /// <param name="owner">The owning object.</param>
            /// <param name="property">The DependencyProperty to watch.</param>
            /// <param name="handler">The action to call out when the DP changes.</param>
            public static void RegisterDepPropCallback(object owner, DependencyProperty property, EventHandler handler)
            {
                // FIXME: We could implement this as an extension, but let's not get
                // too Ruby-like
                var dpd = DependencyPropertyDescriptor.FromProperty(property, owner.GetType());
                dpd.AddValueChanged(owner, handler);
            }
        

        【讨论】:

        • 不幸的是,我很确定 DependencyPropertyDescriptor 是 Silverlight 中的神兽。
        • Silverlight 2 或 3 不支持 DependencyPropertyDescriptor
        猜你喜欢
        • 2011-02-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-12
        • 2011-04-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多