Silverlight: Как да получите известие за промяна в наследено DependencyProperty

Имам контрола, която наследява от (познахте) Control. Искам да получавам известие всеки път, когато свойствата 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 - да, знам, че се нарича много. Имайте предвид обаче, че в някои случаи няма да бъде извикан, въпреки че размерът на шрифта или стилът са се променили.

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