WPF - How to response to DataContextChanged?

I had a problem with Expander:

When the Expander is open, and later on, change context to something with larger content,

the Expander, does not resize and display partialy data with Scrollbars.

 

User need to collapse and re-expand it so the Expander will display it's content - unacceptable.

 

See images below:

 Expanded - data context fits

Expander displays all DataContext - fits.

 

DataContext is larger than Expander size

 

 

The first solution that comes to mind is of course to handle event in code behind.

 

But if you don't want to mess with code behind, than it's a little tricky.

 

DataContextChanged is a regular event and not a RoutedEvent, so we cannot use EventTrigers.

 

The solution is to use a Behavior with Property and Value to be set on the AssociatedObject which listen to DataContextChanged.

The Value will be set for the Property of the AssociatedObject (see line 20).

 

public class DataContextChangedListenerBehavior : Behavior<FrameworkElement>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.DataContextChanged += new DependencyPropertyChangedEventHandler(OnAssociatedObjectDataContextChanged);
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.DataContextChanged -= new DependencyPropertyChangedEventHandler(OnAssociatedObjectDataContextChanged);
    }

    void OnAssociatedObjectDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        object oldValue = AssociatedObject.GetValue(Property);
        if (!object.Equals(oldValue, Value))
        {
            AssociatedObject.SetValue(Property, Value);                
        }
    }

    public static readonly DependencyProperty PropertyProperty =
        DependencyProperty.Register("Property", typeof(DependencyProperty), typeof(DataContextChangedListenerBehavior));

    public DependencyProperty Property
    {
        get { return (DependencyProperty) GetValue(PropertyProperty); }
        set { SetValue(PropertyProperty, value); }
    }

    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value", typeof (object), typeof (DataContextChangedListenerBehavior), 
                                    new PropertyMetadata(null, null, OnCoerceValueCallback));

    private static object OnCoerceValueCallback(DependencyObject d, object basevalue)
    {
        DependencyProperty prop = (DependencyProperty) d.GetValue(PropertyProperty);
        TypeConverter converter = TypeDescriptor.GetConverter(prop.PropertyType);
        object val;
        try
        {
            if (converter != null && converter.CanConvertFrom(basevalue.GetType()))
            {
                val = converter.ConvertFrom(basevalue);
            }
            else
            {
                val = Convert.ChangeType(basevalue, prop.PropertyType);
            }
        }
        catch
        {
            val = basevalue;
        }
        return val;
    }

    public object Value
    {
        get { return GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }
}

 

 Usage:

<Expander DataContext="{Binding SomeDataContext}" >
    <i:Interaction.Behaviors>
        <b:DataContextChangedListenerBehavior Property="Expander.IsExpanded" Value="False" />
    </i:Interaction.Behaviors>
</Expander>

 

 

Enjoy,

Ofir

Thank you for your interest!

We will contact you as soon as possible.

Send us a message

Oops, something went wrong
Please try again or contact us by email at info@tikalk.com