UE4
Topic Author
Posts: 62
Joined: 29 Dec 2017, 06:32

problem in Register command

19 Mar 2018, 04:22

I want to register a custom command in UserControl, I implement it in WPF, but not work C++, some advices?
//command in WPF
		public static readonly DependencyProperty ButtonActionCommandProperty = DependencyProperty.Register(
			"Command", typeof(ICommand), typeof(TouchButton), new UIPropertyMetadata(null));

		public ICommand Command
		{
			get { return (ICommand)GetValue(ButtonActionCommandProperty); }
			set { SetValue(ButtonActionCommandProperty, value); }
		}
//Register command

/*UIData->RegisterProperty<Ptr<BaseCommand>>(CommandProperty, "Command",
		FrameworkPropertyMetadata::Create(Ptr<BaseCommand>(), FrameworkOptions_None));*/

	UIData->RegisterProperty<Ptr<BaseCommand>>(CommandProperty, "Command",
		UIPropertyMetadata::Create(Ptr<BaseCommand>()));

	/*UIData->RegisterProperty<Ptr<BaseComponent>>(CommandParameterProperty, "CommandParameter",
		FrameworkPropertyMetadata::Create(Ptr<BaseComponent>(), FrameworkOptions_None));*/

	UIData->RegisterProperty<Ptr<BaseComponent>>(CommandParameterProperty, "CommandParameter",
		UIPropertyMetadata::Create(Ptr<BaseComponent>()));


//Implemtent ICommand interface

Noesis::ICommand* TouchButton::GetCommand() const
{
	//return nullptr;
	return DependencyObject::GetValue<Ptr<ICommand>>(CommandProperty).GetPtr();
}

void GameGUI::TouchButton::SetCommand(BaseCommand* InCommand)
{
	DependencyObject::SetValue<Ptr<BaseCommand>>(CommandProperty, InCommand);
}

Noesis::BaseComponent* TouchButton::GetCommandParameter() const
{
	return DependencyObject::GetValue<Ptr<BaseComponent>>(CommandParameterProperty).GetPtr();
}

void TouchButton::SetCommandParameter(BaseComponent* InParam)
{
	DependencyObject::SetValue<Ptr<BaseComponent>>(CommandParameterProperty, InParam);
}

//Fire command

if (GetCommand())
		{
			//this line is called
			GetCommand()->Execute(GetCommandParameter());
		}
 
User avatar
hcpizzi
Site Admin
Posts: 316
Joined: 09 Feb 2012, 12:40

Re: problem in Register command

19 Mar 2018, 16:10

Sorry for the late reply. What's exactly the problem? The only thing that I see missing is registering the property itself in your reflection code, like this:
NsProp("Command", & TouchButton::GetCommand, & TouchButton::SetCommand)
        .Meta<TypeConverterMetaData>("Converter<Command>");
 
Can you give that a try and let me know if that fixes it for you?
 
User avatar
hcpizzi
Site Admin
Posts: 316
Joined: 09 Feb 2012, 12:40

Re: problem in Register command

19 Mar 2018, 18:51

I'm sorry, one of my colleagues has pointed out an error in your code. The types in the Get/Set functions are wrong. Try this:
  // Reflection code
    NsProp("Command", &TouchButton::GetCommand, &TouchButton::SetCommand)
        .Meta<TypeConverterMetaData>("Converter<Command>");

    Ptr<UIElementData> data = NsM88eta<UIElementData>(TypeOf<SelfClass>());
    data->RegisterProperty<Ptr<BaseComponent> >(CommandProperty, "Command",
        FrameworkPropertyMetadata::Create(Ptr<BaseComponent>(), FrameworkOptions_None));
    data->RegisterProperty<Ptr<BaseComponent> >(CommandParameterProperty, "CommandParameter",
        FrameworkPropertyMetadata::Create(Ptr<BaseComponent>(), FrameworkOptions_None));
        
   // Getter
 ICommand* TouchButton::GetCommand() const
{
    return NsDynamicCast<ICommand*>(GetValue<Ptr<BaseComponent> >(CommandProperty).GetPtr());
}

// Setter
void TouchButton::SetCommand(ICommand* command)
{
    SetValue<Ptr<BaseComponent> >(CommandProperty, command != 0 ?
        NsStaticCast<BaseComponent*>(command->GetBaseObject()) : 0);
}
Note that the type used is a BaseComponent, that is later cast to ICommand.
 
User avatar
sfernandez
Site Admin
Posts: 2984
Joined: 22 Dec 2011, 19:20

Re: problem in Register command

20 Mar 2018, 00:48

To simplify this code a lot you can derive your command from BaseCommand and make the property use the base type instead of BaseComponent:
data->RegisterProperty<Ptr<BaseCommand>>(CommandProperty, "Command", PropertyMetadata::Create(Ptr<BaseCommand>()));
I want to remark here that adding the property to reflection (NsProp) to register the Command converter is not necessary unless you want that property to be able to parse ApplicationCommands and ComponentCommands from xaml.

The property getter and setter will use both BaseCommand also:
BaseCommand* TouchButton::GetCommand() const
{
  return GetValue<Ptr<BaseCommand>>(CommandProperty);
}
void TouchButton::SetCommand(BaseCommand* command)
{
  SetValue<Ptr<BaseCommand>>(CommandProperty, command);
}
Then you can execute the command like this:
BaseCommand* command = GetCommand();
BaseComponent* param = GetCommandParameter();
if (command->CanExecute(param))
{
  command->Execute(param);
}
 
UE4
Topic Author
Posts: 62
Joined: 29 Dec 2017, 06:32

Re: problem in Register command

20 Mar 2018, 04:31

Thanks, now it works as I expected.
 
User avatar
jsantos
Site Admin
Posts: 3906
Joined: 20 Jan 2012, 17:18
Contact:

Re: problem in Register command

20 Mar 2018, 04:34

You welcome! Marking as solved
 
UE4
Topic Author
Posts: 62
Joined: 29 Dec 2017, 06:32

Re: problem in Register command

22 Mar 2018, 11:20

Can you make more explanation about NsProp?
the Command or BaseCommand is a DependencyProperty, same as WidthProperty? BackgroundProperty?
why does Command need a NsProp? why doesn't others?
 
User avatar
jsantos
Site Admin
Posts: 3906
Joined: 20 Jan 2012, 17:18
Contact:

Re: problem in Register command

27 Mar 2018, 10:28

If you want to support built-in commands, then you need to add a converter for the property. For example, to properly convert the string "ApplicationCommands.Copy" to a valid command. Right now, we only support adding converters to reflection properties, not to dependencies properties. This is exactly the same as in C#, and probably a bit confusing. You can avoid it at all, I don't think you need it.
NsProp("Command", &TouchButton::GetCommand, &TouchButton::SetCommand)
    .Meta<TypeConverterMetaData>("Converter<Command>");

Who is online

Users browsing this forum: No registered users and 87 guests