Rocko Bonaparte
Topic Author
Posts: 39
Joined: 13 Oct 2020, 08:32

Properly showing/hiding a view in Unity with state changes

01 Mar 2021, 17:54

I am having some goofy problems reusing my main menu view. The first problem I think was that I was recreating it each time I was trying to show it. So now I'm preserving the setup and just enabling and disabling it. However, there's a second layer to the problem where it looks like button enable states aren't propagating or something that's going to be a hard problem to show in detail and will take some effort to simplify and see what could be wrong. But for now, I was hoping somebody could check my work for showing and hiding a main menu:
    private NoesisXaml mainMenuXaml;
    private NoesisView mainMenuView;

    public void Show()
    {
        if (mainMenuView == null)
        {
            mainMenuView = GlobalState.Instance.MainCamera.gameObject.GetComponent<NoesisView>();
            mainMenuXaml = (NoesisXaml)UnityEngine.Resources.Load(MainMenuXamlPath, typeof(NoesisXaml));

            // I'm keeping this canary here in case something screws up with loading the main menu later. At least
            // this will point to the crux of the problem.
            if (mainMenuXaml == null)
            {
                Debug.LogError("Could not load the main menu XAML from " + MainMenuXamlPath);
            }

            mainMenuView.Xaml = mainMenuXaml;
            mainMenuView.LoadXaml(true);
        }
        else
        {
            mainMenuView.enabled = true;
        }
    }

    public void Hide()
    {
        mainMenuView.enabled = false;
    }

The button enable/disable logic is trickier because that goes between multiple files, involves the view model, and property change notifications. It works in a standalone test but doesn't in Unity. Is the a gotcha with affecting a viewmodel while the view is disabled or something?
 
Rocko Bonaparte
Topic Author
Posts: 39
Joined: 13 Oct 2020, 08:32

Re: Properly showing/hiding a view in Unity with state changes

02 Mar 2021, 08:09

I'm concluding I have that part down well enough. The bulk of my problem had to do with RelayCommand implementation, per viewtopic.php?f=3&t=2169&p=12273#p12273
 
Rocko Bonaparte
Topic Author
Posts: 39
Joined: 13 Oct 2020, 08:32

Re: Properly showing/hiding a view in Unity with state changes

04 Mar 2021, 07:32

I'm now stuck on a new problem. It looks like if I disable the view, it still gets events. So if I opt for a new game, this will disable the view and start the game. However, if I hit enter on the keyboard, it'll start a new game again despite having disabled the main menu. It's not showing that menu at all.

I also disabled keyboard, mouse, and gamepad, but that doesn't seem to do anything:
        mainMenuView.enabled = false;
        mainMenuView.EnableGamepad = false;
        mainMenuView.EnableMouse = false;
        mainMenuView.EnableKeyboard = false;
I considered it more of a hack regardless, but I'm still left wondering what I really should be doing.
 
User avatar
sfernandez
Site Admin
Posts: 2991
Joined: 22 Dec 2011, 19:20

Re: Properly showing/hiding a view in Unity with state changes

04 Mar 2021, 11:19

Hi Rocko,

I don't know if I'm following your setup, but if I understood correctly you are creating a new NoesisView component for each xaml you want to load, is that right?
What is the purpose of that? Do you need to render them to different cameras?

If you just want to load different xamls into the same scene I recommend using a single NoesisView component with a root xaml:
<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <!-- you can place here everything you need -->
</Grid>
Each view (MainMenu, Settings, HUD,...) can just be a new xaml that you load into that root Grid.

The loading can be done manually:
NoesisView view = GetComponent<NoesisView>();
var xaml = Noesis.GUI.LoadXaml("Assets/Path/To/MainMenu.xaml");
var grid = (Grid)view.Content;
grid.Children.Add(xaml);
Or it can be data driven using MVVM:
<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="clr-namespace:MyTests">
  <Grid.Resources>
    <DataTemplate DataType="{x:Type local:MainMenuVM}">
      <local:MainMenu/>
    </DataTemplate>
    <!-- and the rest of views -->
  </Grid.Resources>
  <ContentControl Content="{Binding ActiveView}"/>
</Grid>
public class ViewModel: INotifyPropertyChanged
{
  private object _activeView;
  public object ActiveView
  {
    get { return _activeView; }
    set
    {
      if (_activeView != value)
      {
        _activeView = value;
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ActiveView");
    }
  }
  
  ...
}
Where that ViewModel is set in root xaml DataContext, and each view is a UserControl that loads its associated xaml.

Does any of this helps?

Who is online

Users browsing this forum: Google [Bot], Semrush [Bot] and 9 guests