Is there any way to databind to TrackAction.CustomProperties.PropertyValue.Value?

Dec 3, 2012 at 9:53 PM

Is there any reason that the CustomProperties.PropertyValue.Value is not a dependency property so that it can be databound?

For example I would like to bind to some custom values that I am logging instead of having to implement it in the code behind. 

 

<UserControl.Resources>
	<local:AnalyticsData x:Key="analyticsData" />
</UserControl.Resources>

<in:Interaction.Behaviors>
	<!-- Omniture -->
	<oa:AppMeasurement 	account="accountid"
        			pageName="{}{msaf.EventArgs.pageName}"
                       		prop1="{}{msaf.EventArgs.prop1}" 
</in:Interaction.Behaviors>
<in:Interaction.Triggers>
	<in:EventTrigger SourceName="LayoutRoot" EventName="Loaded"> 
		<mwab:TrackAction IsEnabled="True"> 
			<mwab:TrackAction.CustomProperties> 
				<mwad:PropertyValue PropertyName="pageName" Value="SearchMain"/> 
				<mwad:PropertyValue PropertyName="prop1" Value="{Binding Source={StaticResource analyticsData}, Path=IsOffline}"/> 
			</mwab:TrackAction.CustomProperties> 
		</mwab:TrackAction>  
	</in:EventTrigger>
</in:Interaction.Triggers>


        
    
Coordinator
Dec 3, 2012 at 10:29 PM

Dependency properties only work on DependencyObjects - and an action cannot be a dependency object.

Dec 6, 2012 at 3:30 AM

I had a chat with our resident Silverlight guru about not being able to bind to PropertyValue.Value and he came up with an idea to get around it. That was to fudge it with an attached property and syncronise the data collected in the attached property with the real custom properties so that it still works. Here it is:

 

 

    public class CustomPropertyCollection : DependencyObjectCollection<BindablePropertyValue>
    {
        internal TrackAction TrackAction { get; set; }
    }

    public static class PropertyValueHelper
    {
        public static readonly DependencyProperty BindableCustomPropertiesProperty =
            DependencyProperty.RegisterAttached("BindableCustomProperties", typeof(CustomPropertyCollection), typeof(PropertyValueHelper), new PropertyMetadata(default(CustomPropertyCollection)));

        public static CustomPropertyCollection GetBindableCustomProperties(TrackAction action)
        {
            var collection = (CustomPropertyCollection)action.GetValue(BindableCustomPropertiesProperty);
            if (collection == null)
            {
                collection = new CustomPropertyCollection();
                action.SetValue(BindableCustomPropertiesProperty, collection);
                collection.TrackAction = action;
                collection.CollectionChanged -= BindableCollectionChanged;
                collection.CollectionChanged += BindableCollectionChanged;
            }
            return collection;
        }

        private static void BindableCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            var collection = (CustomPropertyCollection)sender;
            var action = collection.TrackAction;
            IEnumerable oldItems = e.OldItems;
            IEnumerable newItems = e.NewItems;
            if (e.Action == NotifyCollectionChangedAction.Reset)
            {
                oldItems = collection.ToList();
            }

            if (oldItems != null)
            {
                foreach (BindablePropertyValue oldItem in oldItems)
                {
                    var oldPropertyValue = action.CustomProperties.Single(cp => cp.PropertyName == oldItem.PropertyName);
                    action.CustomProperties.Remove(oldPropertyValue);
                }
            }
            if (newItems != null)
            {
                foreach (BindablePropertyValue newItem in newItems)
                {
                    var newPropertyValue = new PropertyValue();
                    newItem.PropertyValueToSync = newPropertyValue;
                    action.CustomProperties.Add(newPropertyValue);
                }
            }
        }
    }

    public class BindablePropertyValue : DependencyObject
    {
        public string PropertyName { get; set; }

        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(object), typeof(BindablePropertyValue), new PropertyMetadata(default(object), OnValuePropertyChanged));

        private static void OnValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var propertyValue = d as BindablePropertyValue;
            if (propertyValue != null && propertyValue.PropertyValueToSync != null)
            {
                propertyValue.PropertyValueToSync.Value = propertyValue.Value;
            }
        }

        public string Value
        {
            get { return GetValue(ValueProperty).ToString(); }
            set { SetValue(ValueProperty, value); }
        }

        private PropertyValue _propertyValueToSync;
        internal PropertyValue PropertyValueToSync
        {
            get { return _propertyValueToSync; }
            set
            {
                _propertyValueToSync = value;
                value.PropertyName = PropertyName;
                value.Value = Value;
            }
        }
    }

        <in:Interaction.Triggers>
            <in:EventTrigger SourceName="LayoutRoot" EventName="Loaded" >
                <mwab:TrackAction>
                    <local:PropertyValueHelper.BindableCustomProperties>
                        <local:BindablePropertyValue PropertyName="pageName" Value="SearchMainPage"/>
                        <local:BindablePropertyValue PropertyName="prop1"
                                Value="{Binding Source={StaticResource analyticsData}, Path=IsOffline, Mode=OneWay}"/>                     
                    </local:PropertyValueHelper.BindableCustomProperties>                                      
                </mwab:TrackAction>
            </in:EventTrigger>
        </in:Interaction.Triggers>

 

Jan 5 at 6:04 AM