nghiemvdv
Topic Author
Posts: 4
Joined: 01 Jun 2022, 10:05

Create a menu setting popup with a slider inside ContentControl

01 Jun 2022, 11:15

I'm creating a slider that modifies a variable inside unreal engine by using onewaytosource binding mode (changing volume setting for example). Now I need to create an event that triggered when the value changed but I'm having a hard time doing.
I have a Popup element with a ContentControl child that has the property Style asign to a Style that has the Slider. Something like this
<UserControl x:Class="MyNameSpace.Home" ...>
	<UserControl.Resources>
		<ControlTemplate x:Key="Template.ItemToolTip" TargetType="{x:Type ContentControl}">
			<Grid>
				<StackPanel Orientation="Horizontal" Margin="0,10,0,10" HorizontalAlignment="Stretch">
					<TextBlock Text="Volume: "/>
	                <Slider x:Name="MasterVolume" Margin="0,10,0,10" Width="270" Value="{Binding MasterVolume, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}" ValueChanged="{Binding OnMasterVolumeChanged}">
	                </Slider>
				</StackPanel>
			</Grid>
		</ControlTemplate>
		<Style x:Key="Style.ItemToolTip" TargetType="{x:Type ContentControl}">
			<Setter Property="Template" Value="{StaticResource Template.ItemToolTip}"/>
		</Style>
	</UserControl.Resources>

	<Grid>
		<Popup IsOpen="{Binding IsChecked, ElementName=MenuButton}" x:Name="Popup" StaysOpen="False" AllowsTransparency="True" Placement="RelativePoint" PlacementTarget="{Binding ElementName=PopupPosition}">
			<ContentControl x:Name="MenuPopup" Style="{StaticResource Style.ItemToolTip}"/>
		</Popup>
	</Grid>
</UserControl>
The popup is enabled when a button is pressed. When changing the slider will change the "VolumeMaster" in unreal. I'm having trouble binding the ValueChanged property of Slider to an event so I'd like to ask how to correctly bind this property when I'm at the UserControl root element (in blueprint and c++ if possible). The intention was to create a function (blueprint) with the name "OnMasterVolumeChanged" to print the current value of Slider. Tried using FindName to search for the slider but failed. I would like to be able to bind the function without changing the above structure if possible.

Can anyone guide me to the right direction. I'm only a beginner in xaml/wpf so any pointer would be appreciated.
 
User avatar
sfernandez
Site Admin
Posts: 3005
Joined: 22 Dec 2011, 19:20

Re: Create a menu setting popup with a slider inside ContentControl

01 Jun 2022, 13:37

Hi,

I think you don't need to create a ControlTemplate+Style in order to show it in the popup (unless you are reusing that style in more places), you can just have the elements directly inside the popup. This will allow you to search for any element inside the popup by calling FindName from the UserControl code-behind. If you still want to use a template, you then need to first call FindName to find the "MenuPopup" element, and then call on that element GetTemplateChild to search for elements inside the template.

Regarding ValueChanged, you should follow the documentation about events. Just set the name of the method you want to call when the event is raised and override ConnectEvent in the usercontrol code-behind to hook that method with the event.
<UserControl x:Class="MyNameSpace.Home" ...>
  <Grid>
    <Popup IsOpen="{Binding IsChecked, ElementName=MenuButton}" x:Name="Popup" StaysOpen="False" AllowsTransparency="True"
      Placement="RelativePoint" PlacementTarget="{Binding ElementName=PopupPosition}">
      <Grid>
        <StackPanel Orientation="Horizontal" Margin="0,10,0,10" HorizontalAlignment="Stretch">
          <TextBlock Text="Volume: "/>
          <Slider x:Name="MasterVolume" Margin="0,10,0,10" Width="270"
            Value="{Binding MasterVolume, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}" ValueChanged="OnMasterVolumeChanged">
          </Slider>
        </StackPanel>
      </Grid>
    </Popup>
  </Grid>
</UserControl>
class Home...
{
  bool ConnectEvent(BaseComponent* source, const char* event, const char* handler) override
  {
    NS_CONNECT_EVENT(Slider, ValueChanged, OnMasterVolumeChanged);
    return false;
  }
  
  void OnMasterVolumeChanged(BaseComponent* sender, const RoutedPropertyChangedEventArgs<float>& args)
  {
    ...
  }
};
Hope this helps.
 
nghiemvdv
Topic Author
Posts: 4
Joined: 01 Jun 2022, 10:05

Re: Create a menu setting popup with a slider inside ContentControl

02 Jun 2022, 10:57

Thanks it worked! I also learned that GetTemplateChild doesn't return anything if the popup is not enabled.
But there's a problem. After I implemented the ConnectEvent method for the Home class exactly like above and assign the OnMasterVolumeChanged to ValueChanged in xaml, it worked but crashed when I stop the game in ue editor when the slider's thumb wasn't left at the original position/value (i.e. 0.0). When I start the game and move the slider's thumb back and forth then leave it at the original position, nothing crashes when I exit the game.
The exception throws me to the mPtr->Release() in Reset method of Ptr class of Noesis.
I didn't save any reference to any object. Tried to comment out the ConnectEvent method then rebuild, it didn't crash so the problem is the ConnectEvent I think.
 
User avatar
jsantos
Site Admin
Posts: 3935
Joined: 20 Jan 2012, 17:18
Contact:

Re: Create a menu setting popup with a slider inside ContentControl

02 Jun 2022, 11:41

Does it crash if you leave OnMasterVolumeChanged empty?

Could you paste here the code for OnMasterVolumeChanged?
 
nghiemvdv
Topic Author
Posts: 4
Joined: 01 Jun 2022, 10:05

Re: Create a menu setting popup with a slider inside ContentControl

02 Jun 2022, 11:46

I just checked, it still crashes when OnMasterVolumeChanged is left empty. Here's the definition:
void Home::OnMasterVolumeChanged(Noesis::BaseComponent* sender, const Noesis::RoutedPropertyChangedEventArgs<float>& args)
{
	if (auto slider = Noesis::DynamicCast<Noesis::Slider*>(sender))
	{
		UE_LOG(LogTemp, Warning, TEXT("c++ Master: %f"), slider->GetValue());
	}
	else
	{
		UE_LOG(LogTemp, Warning, TEXT("sender is not slider!!!"));
	}
}
 
User avatar
sfernandez
Site Admin
Posts: 3005
Joined: 22 Dec 2011, 19:20

Re: Create a menu setting popup with a slider inside ContentControl

06 Jun 2022, 16:46

Could you try removing the binding from the Slider's Value property while still keeping the ConnectEvent implementation?
Let me know if you get a crash when stopping.
 
nghiemvdv
Topic Author
Posts: 4
Joined: 01 Jun 2022, 10:05

Re: Create a menu setting popup with a slider inside ContentControl

08 Jun 2022, 13:05

- Not assigning any value to the Value property (effectively not binding) while still keeping the ConnectEvent implementation doesn't trigger any crash
- Tried to binding to a variable that doesn't exist (say changing the name from VolumeMaster to VolumeMaster123) while still keeping the ConnectEvent implementation, it crashed
- Kept the binding attempt and the ConnectEvent impl but assinging ValueChanged property to an invalid value also doesn't trigger any crash
 
User avatar
sfernandez
Site Admin
Posts: 3005
Joined: 22 Dec 2011, 19:20

Re: Create a menu setting popup with a slider inside ContentControl

06 Jul 2022, 18:08

We found and fixed the issue you described, it was trying to call the event handler during the control destruction.
The fix will be available in the next version release (3.1.6).
Thanks a lot for your feedback and help.

Who is online

Users browsing this forum: Ahrefs [Bot], ersenal and 3 guests