Changing elements in UserControls
If a usercontrol is binding it's internal variables in the method OnPostInit (as is recommended in your documentation), when and where is the best practice for calling methods on that UserControl?
To elaborate:
I have a usercontrol:
And it's code behind, for unity:
I want to be able to create a popup over my main window to show a UserControl, with the following method:
The problem here is that the Loaded event is fired *before* OnPostInit() - I get a null pointer exception setting the label or content as they have not been initialized yet.
It seems that there's no event which is fired just after OnPosInit() is called on the UserControl, giving no native non-databinding way to add content to your control which is created externally.
What am I missing?
It's possible, of course, to add my own event and call it at the end of OnPostInit(), but that doesn't seem right for larger scale systems and feels against the grain of Noesis's intended direction.
Is there a better solution to this problem?
To elaborate:
I have a usercontrol:
Code: Select all
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
x:Class="FullscreenPopupContainer"
UseLayoutRounding="True" d:DesignWidth="725.167" d:DesignHeight="339.667"
Margin="1, 4, 0, 0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="5*"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="5*"/>
<RowDefinition />
</Grid.RowDefinitions>
<Button Name="BackgroundCloserButton" Opacity="0" Grid.Row="99" Grid.ColumnSpan="99" />
<Rectangle Fill="Black" Opacity="0.6" Grid.ColumnSpan="99" Grid.RowSpan="99" />
<Grid Grid.Column="1" Grid.Row="1" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="28" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="1" Grid.Row="0" Background="#FF4E7BF5" />
<Path Data="F0 M0,20 L20,00 100,0 100,100 00,100"
StrokeThickness="0" Stroke="White" Fill="#FF4E7BF5"/>
<Label Grid.Column="1" Grid.Row="0" Content="Title" Name="TitleLabel" Margin="-30, 2, 0, 0"/>
<Border Visibility="Collapsed" BorderThickness="0" Grid.Row="0"
CornerRadius="20,0,0,0" Background="#FF4E7BF5"/>
</Grid>
<Grid Grid.Row="1">
<Border BorderThickness="2, 2, 2, 2" BorderBrush="#FF4E7BF5" />
<Grid x:Name="ControlSpace" Margin="2"/>
</Grid>
</Grid>
</Grid>
</Grid>
</UserControl>
Code: Select all
using UnityEngine;
using System.Collections;
using Noesis.UserControls;
using Noesis;
using System;
[Noesis.Extended]
[Noesis.UserControlSource("Assets/GUI/Containers/FullscreenPopupContainer.xaml")]
public class FullscreenPopupContainer : Noesis.UserControl {
Label titleLabel;
Grid contentPanel;
public void Start()
{
}
// Use this for initialization
public void OnPostInit()
{
titleLabel = FindName<Label>("TitleLabel");
contentPanel = FindName<Grid>("ControlSpace");
Debug.Log("Post init called");
}
public void SetLabel(string label)
{
titleLabel.SetContent(label);
}
public void AddControl(UserControl contentControl)
{
contentPanel.GetChildren().Add(contentControl);
}
}
Code: Select all
public void AddPopup(UserControl control, string title)
{
FullscreenPopupContainer popupContainer = NoesisGUISystem.LoadXaml<FullscreenPopupContainer>("Assets/GUI/Containers/FullscreenPopupContainer.xaml");
popupContainer.Loaded += delegate
{
if (control != null) {
popupContainer.AddControl(control);
}
popupContainer.SetLabel(title);
};
contentGrid.GetChildren().Add(popupContainer);
}
It seems that there's no event which is fired just after OnPosInit() is called on the UserControl, giving no native non-databinding way to add content to your control which is created externally.
What am I missing?
It's possible, of course, to add my own event and call it at the end of OnPostInit(), but that doesn't seem right for larger scale systems and feels against the grain of Noesis's intended direction.
Is there a better solution to this problem?
-
sfernandez
Site Admin
- Posts: 3188
- Joined:
Re: Changing elements in UserControls
Hi,
We have to improve this scenario because the Init/Load behavior does not correspond to WPF, and people gets very confused.
In your example, and with the current implementation of NoesisGUI, you need to wait after control is added to the tree to ensure that OnPostInit was called. So your code should be modified as follows to make it work:
Hope this helps.
Regards,
- Sergio
We have to improve this scenario because the Init/Load behavior does not correspond to WPF, and people gets very confused.
In your example, and with the current implementation of NoesisGUI, you need to wait after control is added to the tree to ensure that OnPostInit was called. So your code should be modified as follows to make it work:
Code: Select all
public void AddPopup(UserControl control, string title)
{
// Here you can also create the popup calling just the new operator:
//FullscreenPopupContainer popupContainer = new FullscreenPopupContainer();
FullscreenPopupContainer popupContainer = NoesisGUISystem.LoadXaml<FullscreenPopupContainer>("Assets/GUI/Containers/FullscreenPopupContainer.xaml");
contentGrid.GetChildren().Add(popupContainer); // Loaded is called first, then OnPostInit
if (control != null) {
popupContainer.AddControl(control);
}
popupContainer.SetLabel(title);
}
Regards,
- Sergio
Who is online
Users browsing this forum: No registered users and 3 guests