0

I need to raise an event on changing a DP (called CurrentItem) value of a UserControl (called MenuButton) to notify another UserControl to change its Title DP. Everything works fine except old-value of CurrentItem is used in target DP. How can I force it to use new-value of the CurrentItem DP?


public partial class MenuButton : UserControl
{
    ...

    public struct ZoneMenuItem
    {
        public string MenuTitle
        {
            get;
            set;
        }

        public string ZoneTitle
        {
            get;
            set;
        }

        public ZoneMenuItem(string menuTitle, string zoneTitle)
        {
            this = new ZoneMenuItem();

            this.MenuTitle = menuTitle;
            this.ZoneTitle = zoneTitle;
        }
    }

    #region ________________________________________  CurrentItemChanged RoutedEvent

    public event RoutedEventHandler CurrentItemChanged
    {
        add { AddHandler(CurrentItemChangedEvent, value); }
        remove { RemoveHandler(CurrentItemChangedEvent, value); }
    }

    public static readonly RoutedEvent CurrentItemChangedEvent =
        EventManager.RegisterRoutedEvent("CurrentItemChanged", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(MenuButton));

    #endregion

    #region ________________________________________  CurrentItem DependencyProperty

    public ZoneMenuItem CurrentItem
    {
        get { return (ZoneMenuItem)GetValue(CurrentItemProperty); }
        set { SetValue(CurrentItemProperty, value); }
    }

    public static readonly DependencyProperty CurrentItemProperty =
        DependencyProperty.Register("CurrentItem",
                                    typeof(ZoneMenuItem),
                                    typeof(MenuButton),
                                    new FrameworkPropertyMetadata(new ZoneMenuItem(), FrameworkPropertyMetadataOptions.None, OnCurrentItemPropertyChanged));

    private static void OnCurrentItemPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        MenuButton instance = sender as MenuButton;

        if (instance != null)
        {
            instance.RaiseEvent(new RoutedEventArgs(MenuButton.CurrentItemChangedEvent));
        }
    }

    #endregion
}

As shown above, I raised an event on CurrentItem property changed. It's used in another UserControl like so:

<i:EventTrigger SourceName="menuButton" EventName="CurrentItemChanged">
    <ei:ChangePropertyAction TargetObject="{Binding}" PropertyName="Title">
        <ei:ChangePropertyAction.Value>
            <Binding ElementName="menuButton" Path="CurrentItem.ZoneTitle"/>
        </ei:ChangePropertyAction.Value>
    </ei:ChangePropertyAction>
</i:EventTrigger>

where

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"

Update 1:

I found a workaround for it via using code-behind instead of utilizing interactivity triggers. (Why does it work?!)

menuButton.CurrentItemChanged += menuButton_CurrentItemChanged;


private void menuButton_CurrentItemChanged(object sender, RoutedEventArgs e)
{
    this.Title = (sender as MenuButton).CurrentItem.ZoneTitle;
}

Update 2:

I tried to use an EventTrigger to do all tasks in XAML only, but it behaves exactly the same as an interactivity trigger!

<vc:MenuButton x:Name="menuButton" VerticalAlignment="Center" Margin="3,3,0,0">
    <vc:MenuButton.Triggers>
        <EventTrigger SourceName="menuButton" RoutedEvent="vc:MenuButton.CurrentItemChanged">
            <BeginStoryboard>
                <Storyboard>
                    <StringAnimationUsingKeyFrames Storyboard.Target="{Binding}" Storyboard.TargetProperty="Title">
                        <DiscreteStringKeyFrame KeyTime="0" Value="{Binding ElementName=menuButton, Path=CurrentItem.ZoneTitle}"/>
                    </StringAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </vc:MenuButton.Triggers>
</vc:MenuButton>

It's too strange! Why do these triggers have a different behavior than the event handler?

Mehdi
  • 2,194
  • 2
  • 25
  • 39

1 Answers1

0

If I haven't overlooked other, then the cause could because the structs are passed by value. This cause to have two copy. One which is used by your binding and other which is the original one. This means, if your binding update the struct which is in memory and not the original.

S.N
  • 4,910
  • 5
  • 31
  • 51
  • Thanks @nair, I'll test it replacing struct with a class. **Edit:** Doesn't work! – Mehdi May 09 '13 at 07:48
  • Can you check whether you have implemented INotificationPropertyChanged ? Eg:http://msdn.microsoft.com/en-us/library/ms743695.aspx – S.N May 09 '13 at 08:24
  • @nair That is not necessary here, as the property is a [dependency property](http://msdn.microsoft.com/en-us/library/ms752914.aspx). Also, the change notification is apparently working: the property changed handler is where the RoutedEvent is raised. – Clemens May 09 '13 at 08:27
  • Updated my question, any idea? – Mehdi May 14 '13 at 05:41