darthmaule2
Topic Author
Posts: 98
Joined: 23 Oct 2014, 19:54

C++ routed event troubles

13 Dec 2014, 16:54

I'm trying to follow the documentation for routed events and declare a simple routed event...
NS_DECLARE_SYMBOL(ToggleButtonVisibility)

class SBToggleButton : public Button, public INotifyPropertyChanged
{	
public:
	SBToggleButton() : _toggleButtonVisibility(Visibility_Visible)
	{
	}

	~SBToggleButton()
    {
		_destroyedEvent(this);
    }

	Visibility GetToggleButtonVisibility() const
    {
		return _toggleButtonVisibility;
    }
		
    void SetToggleButtonVisibility(const Visibility toggleButtonVisibility)
    {
        if (_toggleButtonVisibility != toggleButtonVisibility)
        {
            _toggleButtonVisibility = toggleButtonVisibility;
            _changedEvent(this, NSS(ToggleButtonVisibility));
        }
    }

    PropertyChangedEventHandler& PropertyChanged()
    {
        return _changedEvent;
    }
	
    DestroyedEventHandler& Destroyed()
    {
        return _destroyedEvent;
    }

	static const RoutedEvent* DownloadCompletedEvent;
    UIElement::Event<RoutedEventHandler> DownloadCompleted()
    {
        return Event<RoutedEventHandler>(this, DownloadCompletedEvent);
    }

protected:
	virtual void OnDownloadCompleted(const Ptr<BaseComponent>& downloadedContent)
    {
        RoutedEventArgs args(this, DownloadCompletedEvent);
        RaiseEvent(args);
    }

private:
	Visibility _toggleButtonVisibility;
	PropertyChangedEventHandler _changedEvent;
    DestroyedEventHandler _destroyedEvent;

    NS_IMPLEMENT_INLINE_REFLECTION(SBToggleButton, Button)
    {
        NsMeta<TypeId>("SBToggleButton");
		NsImpl<INotifyPropertyChanged>();
		NsProp("ToggleButtonVisibility", &SBToggleButton::GetToggleButtonVisibility, &SBToggleButton::SetToggleButtonVisibility);

		Ptr<UIElementData> data = NsMeta<UIElementData>(TypeOf<SelfClass>());
		data->RegisterEvent(DownloadCompletedEvent, "DownloadCompleted", RoutingStrategy_Bubbling);
    }
};
But I get this linker error:
Error 215 error LNK2001: unresolved external symbol "public: static class Noesis::Gui::RoutedEvent const * const SBToggleButton::DownloadCompletedEvent" (?DownloadCompletedEvent@SBToggleButton@@2PEBVRoutedEvent@Gui@Noesis@@EB) C:\code\NoesisGUI\NoesisGuiProto\Tutorial05\NoesisGuiExtensions.obj Tutorial05

Any idea what I'm doing wrong?

Thanks.
 
User avatar
sfernandez
Site Admin
Posts: 3184
Joined: 22 Dec 2011, 19:20

Re: C++ routed event troubles

13 Dec 2014, 17:14

Hi,

It seems that the documentation sample is not complete, the code for the event static member initialization is missing.
You have to add in any implementation unit (SBToggleButton.cpp for example) the following line:
const RoutedEvent* SBToggleButton::DownloadCompletedEvent;
Let me know if it fixes your link error.

Regards,
- Sergio
 
darthmaule2
Topic Author
Posts: 98
Joined: 23 Oct 2014, 19:54

Re: C++ routed event troubles

13 Dec 2014, 18:11

Fixed, thanks.
 
darthmaule2
Topic Author
Posts: 98
Joined: 23 Oct 2014, 19:54

Re: C++ routed event troubles

16 Dec 2014, 12:43

So it seems like my routed event is compiling and being parsed correctly but it doesn't seem to trigger any action.

Here is my code-behind that declares the routed event:
class SoftButtonControl : public UserControl
{
public:
	SoftButtonControl()
	{		
	}

	~SoftButtonControl()
        {
        }

	static const RoutedEvent* TapDownEvent;
        UIElement::Event<RoutedEventHandler> TapDown()
	{
		return Event<RoutedEventHandler>(this, TapDownEvent);
	}

	void OnMouseDown(const MouseButtonEventArgs &e)
	{
		RoutedEventArgs args = *new RoutedEventArgs(this, TapDownEvent);
                RaiseEvent(args);
	}

private:
    NS_IMPLEMENT_INLINE_REFLECTION(SoftButtonControl, UserControl)
    {
        NsMeta<TypeId>("SoftButtonControl");	
		Ptr<UIElementData> data = NsMeta<UIElementData>(TypeOf<SelfClass>());
		data->RegisterEvent(TapDownEvent, "TapDown", RoutingStrategy_Bubbling);
    }
};
I then have this xaml:
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d"  VerticalContentAlignment="Bottom"
             x:Class="SoftButtonControl">
    <UserControl.Resources>

      <Storyboard x:Key="TapDownStoryboard">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(TranslateTransform.Y)" Storyboard.TargetName="ToggleButtonTransform">
          <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="36.5"/>
        </DoubleAnimationUsingKeyFrames>
      </Storyboard>

      <ControlTemplate x:Key="SBToggleButtonTemplate">
        <Grid Background="Transparent">
          <Path ...
          </Path>
          <Border Height="70.5" Width="57.8" CornerRadius="5" Background="{StaticResource SoftButtonBackgroundBrush}">
            <Grid>
              <Rectangle x:Name="toggleRect" Width="56" Height="33" VerticalAlignment="Top" Margin="0, 0.5, 0, 0" RadiusX="5" RadiusY="5"
                     Fill="{StaticResource SoftButtonBorderBrush}" RenderTransformOrigin="0,0">
                <Rectangle.Stroke>
                  <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FF999C9F"/>
                    <GradientStop Color="#FFA6A4A4"/>
                  </LinearGradientBrush>
                </Rectangle.Stroke>
                <Rectangle.RenderTransform>
                    <TranslateTransform x:Name="ToggleButtonTransform"/>
                </Rectangle.RenderTransform>
              </Rectangle>
            </Grid>
          </Border>
        </Grid>
        <ControlTemplate.Triggers>
            <EventTrigger RoutedEvent="SoftButtonControl.TapDown">
            <EventTrigger.Actions>
              <BeginStoryboard Storyboard="{StaticResource TapDownStoryboard}"/>
            </EventTrigger.Actions>
          </EventTrigger>
        </ControlTemplate.Triggers>
        </ControlTemplate>
    </UserControl.Resources>

   <UserControl>
      <Grid>
      <SBToggleButton x:Name="sbToggleButton" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Stretch"  Height="100" Focusable="False" FocusVisualStyle="{x:Null}"
        Template="{StaticResource SBToggleButtonTemplate}" Visibility="{Binding ToggleButtonVisibility}"/>
    </Grid>
  </UserControl>
Is there anything else I need to do to register for the routed event? Or is enough to just add an EventTrigger with the routed event name? When I click on my control, OnMouseDown is called and the event is raised but it never triggers the storyboard.

Thanks.
 
darthmaule2
Topic Author
Posts: 98
Joined: 23 Oct 2014, 19:54

Re: C++ routed event troubles

16 Dec 2014, 13:46

I think I partially fixed it by moving the routed event into the SBToggleButton class. But now when I raise the event from the OnMouseDown function in the SBToggleButton class, the storyboard is getting triggered, but then now I get a runtime error:
Can't animate path '(TranslateTransform.y)' because root element is frozen
 
User avatar
sfernandez
Site Admin
Posts: 3184
Joined: 22 Dec 2011, 19:20

Re: C++ routed event troubles

16 Dec 2014, 16:36

This is a known limitation of our animation system (viewtopic.php?f=3&t=442&p=2168&hilit=be ... ozen#p2154).

You have to animate the Freezable object property by referencing it through the FrameworkElement where the Freezable is set:
<DoubleAnimation
    Storyboard.TargetName="toggle"
    Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.Y)" .../>
<SBToggleButton x:Name="toggle" ...>
    <SBToggleButton.RenderTransform>
     <TranslateTransform X="0" />
    </SBToggleButton.RenderTransform>
</SBToggleButton>
Sorry for the inconvenience.

Who is online

Users browsing this forum: No registered users and 6 guests