Przygody z oprogramowaniem
  • Start
  • Szkolenia
    • Szkolenia otwarte
    • Katalog szkoleń
  • Usługi
    • Konsulting
    • Mentoring
    • Research & Development
  • Blog
  • Wiedza
    • Strefa wiedzy
    • BFsharp
    • SaaS
  • Klienci
  • Kontakt
0

Jak ustawić DependencyProperty?

13 December, 2011-C#, Silverlight, WPF

Jak ustawić DependencyProperty programowo? Otóz odpowiedź na to pytanie wydaje się bardzo prosta – użyć funkcji SetValue:

public void SetValue( DependencyProperty dp, Object value )

Niestety wymaganiem jest tu posiadanie instancji DependencyProperty.
Co jednak jeśli chcemy ustawić property znając tylko jego ścieżkę, np. “RenderTransform.Children[0].Angle”. By poradzić sobie z tym problemem można skorzystać z poniższej klasy.

public static class DependencyPropertyHelper
{
    private static readonly DependencyProperty DummyProperty = 
        DependencyProperty.RegisterAttached( "Dummy",
            typeof(Object), typeof(DependencyObject),
            new UIPropertyMetadata(null));

    private static readonly DependencyObject _object =
        new DependencyObject();

    public static void SetValue(object container,
        string dependencyProperty, object value)
    {
        Binding binding = new Binding(dependencyProperty) 
            { Source = container, Mode = BindingMode.TwoWay };

        BindingOperations.SetBinding(_object, DummyProperty, binding);
        _object.SetValue(DummyProperty, value);
#if SL
        BindingOperations.SetBinding(_object, DummyProperty, null);
#elif WPF
        BindingOperations.ClearBinding(_object, DummyProperty);
#endif
    }

    public static object GetValue(object container,
        string dependencyProperty)
    {
        Binding binding = new Binding(dependencyProperty) 
            { Source = container };
        BindingOperations.SetBinding(_object, DummyProperty, binding);

        return _object.GetValue(DummyProperty);
    }
}

Wykorzystuje ona pewien trick – używa bindingu do pobierania i ustawiania property.

Czytaj dalej | Dyskutuj
3

Behaviors, Triggers and memory leaks in Silverlight

20 January, 2010-Debugging, Silverlight

Recently I was investigating strange memory leaks in Silverlight application. After switching back and forth through the screens the memory was gradually growing. Because of the lack of silverlight profiler I used windbg to diagnose the problem. It turned out that none of the view models and controls were released.

After several hours of digging I found that the problem was the behaviors and triggers from Blend samples (Expression.Samples.Interactivity). If you remove controls that use some of the behaviors or trigger actions (these which subscribe internally on events) you’re in trouble. The memory used by them is never released. If your application is small there is probably no problem. However if you’re developing more complicated ones with lot of screens that have to work for several hours the memory consumption can be unacceptable.

The solution

Here is the workaround I used to correct this situation. Before removing any control you should detach all triggers and behaviors.

static void UnwireBehaviors(object current)
{
    DependencyObject parent = current as DependencyObject;

    if (parent != null)
    {
        Interaction.GetTriggers(parent).Clear();
        Interaction.GetBehaviors(parent).Clear();

        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
        {
            var child = VisualTreeHelper.GetChild(parent, i);
            UnwireBehaviors(child);
        }
    }
}

However it's not all. There is a couple of bugs in the code from codeplex too. The class BindingListener doesn't call Detach on it's internal structures and doesn't wire events in some cases. The corrected code should look something like this:

public class BindingListener 
{
    [...]
    private void Detach() 
    {
        if (this.listener != null)
        {
            this.listener.Detach(); // This is not called in the original samples
            this.ReturnListener();
        }
    }

    private DependencyPropertyListener GetListener() 
    {
        DependencyPropertyListener listener;

        if (BindingListener.freeListeners.Count != 0) 
        {
            listener = BindingListener.freeListeners[BindingListener.freeListeners.Count - 1];
            BindingListener.freeListeners.RemoveAt(BindingListener.freeListeners.Count - 1);

            // return listener; This was called in the original samples preventing event wiring  
        }
        else
            listener = new DependencyPropertyListener();

        listener.Changed += this.HandleValueChanged;

        return listener;
    }

    [...]
}
Czytaj dalej | Dyskutuj

Kategorie

Architecture BFsharp Blog Business Framework C# CqRS DDD Debugging DSL EntityFramework Formula JavaScript Linq NHibernate SaaS Silverlight SQL Visual Studio WPF Wzorce

O mnie


RSS Feed

© macmichal.pl 2011 Wszystkie prawa zastrzeżone