Silverlight: как получить уведомление об изменении унаследованного DependencyProperty

У меня есть элемент управления, который наследуется от (как вы уже догадались) элемента управления. Я хочу получать уведомления при изменении свойств FontSize или Style. В WPF я бы сделал это, вызвав DependencyProperty.OverrideMetadata(). Конечно, таким полезным вещам не место в Silverlight. Итак, как можно получать такие уведомления?


person MojoFilter    schedule 07.05.2009    source источник


Ответы (5)


Я думаю, что здесь есть лучший способ. Все равно надо смотреть плюсы и минусы.

 /// 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.

person amazedsaint    schedule 02.12.2009
comment
Мне нравится, что это более приятный способ свернуть эту уродливую привязку, но это ужасно тяжелый способ получать уведомления об изменении свойств. - person MojoFilter; 03.12.2009
comment
Пока нам нужно делать это полностью из кода, я думаю, у нас нет другого варианта, пока мы не получим DependencyPropertyDescriptor в Silverlight от MS. - person amazedsaint; 04.12.2009
comment
Я также использовал этот подход, к сожалению, он пропускает память. По моему опыту, он будет содержать ссылку на любой элемент, с которым вы его используете, который, в свою очередь, будет удерживать другие объекты. Виновником, по-видимому, является обратный вызов, который сохранит ссылку на ваше представление на весь срок службы вашего приложения. - person Ian Oakes; 13.12.2010
comment
Это работает (+1!), но, как сказал Ян, это не оптимально. В качестве обходного пути я переместил прикрепленное свойство (в моем случае с именем ListenAttachedIsEnabledProperty в класс, который я хочу переопределить, и добавил следующие две строки в конструктор var b = new Binding("IsEnabled") { Source = this }; SetBinding(ListenAttachedIsEnabledProperty, b); - person Dr. Andrew Burnett-Thompson; 01.03.2012
comment
он будет вызываться при вызове RegisterForNotification для нескольких текстовых полей, вероятно, потому, что вы не можете создать несколько свойств DependencyProperties с одним и тем же именем. - person Firo; 27.05.2013

Это довольно отвратительный хак, но вы можете использовать двустороннюю привязку для имитации этого.

то есть иметь что-то вроде:

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>

затем подключитесь к событию слушателя в вашем подклассе управления.

person toshok    schedule 08.09.2009
comment
Когда свойство MyControlSubclass FontSize изменится, привязка будет ясной, поэтому кажется, что она не работает? нет? - person Amir Karimi; 23.08.2011

Вы не можете прослушивать извне уведомления об изменении свойств зависимостей.

Вы можете получить доступ к метаданным свойств зависимостей с помощью следующей строки кода:

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

Однако единственным общедоступным элементом, который предоставляется, является «DefaultValue».

В WPF есть множество способов сделать это. Но в настоящее время они не поддерживаются Silverlight 2 или 3.

person markti    schedule 07.05.2009

Единственное решение, которое я вижу, это слушать событие LayoutUpdated — да, я знаю, что оно называется много. Однако обратите внимание, что в некоторых случаях он не будет вызываться, даже если FontSize или Style изменились.

person Vlad Filyakov    schedule 08.05.2009

Это то, что я всегда использую (хотя не тестировал его на 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);
    }
person Ana Betts    schedule 07.05.2009
comment
К сожалению, я почти уверен, что DependencyPropertyDescrtiptors — мифические звери в Silverlight. - person MojoFilter; 07.05.2009
comment
DependencyPropertyDescriptor не поддерживается Silverlight 2 или 3 - person markti; 08.05.2009