consoleframework icon indicating copy to clipboard operation
consoleframework copied to clipboard

FindChildByName returns null when trying to get a MenuItem

Open ktodyruik opened this issue 10 years ago • 3 comments

Hi,

I'm trying to attach an event handler to an exit menu item. FindChildByName<> always returns null when I try to get the menu item.

Program.cs

WindowsHost windowsHost = (WindowsHost) ConsoleApplication.LoadFromXaml("HelloWorld.windows-host.xml", null);
            Window mainWindow = (Window) ConsoleApplication.LoadFromXaml("HelloWorld.main.xml", null);
            windowsHost.Show(mainWindow);
            MenuItem exit = windowsHost.MainMenu.FindChildByName<MenuItem>("exit");
           // exit is null

windows-host.xml

<WindowsHost>
  <WindowsHost.MainMenu>
    <Menu HorizontalAlignment="Stretch">
      <Menu.Items>
        <MenuItem Title="_Application" Type="Submenu" Gesture="Alt+F" Name="application">
          <MenuItem Title="_About" Name="about"/>
          <MenuItem Title="E_xit" TitleRight="Alt+X" Name="exit"/>
        </MenuItem>
      </Menu.Items>
    </Menu>
  </WindowsHost.MainMenu>
</WindowsHost>

ktodyruik avatar Oct 02 '14 00:10 ktodyruik

Unfortunately, Menu is constructed using popup window to display menu items. And this popup is displayed as regular window (by calling WindowsHost), so menu items are not direct children of Menu in visual tree. You can try to use commands (see Commands example):

<MenuItem Title="_Run command" TitleRight="Ctrl+R" Gesture="Ctrl+R"
                    Command="{Binding MyCommand, Mode=OneTime}"/>

It is the simpliest way at now.. I'll think about how to get direct instances to objects like this more gracefully.

elw00d avatar Oct 02 '14 18:10 elw00d

Thanks. That worked for my exit menu item. Could you show me an example of how to create a window, and then open it from the menu item click binding command? I tried this, but it doesn't seem to work:

 private static void Main(string[] args)
        {
            DataContext dataContext = new DataContext();

            WindowsHost windowsHost = (WindowsHost)ConsoleApplication.LoadFromXaml("HelloWorld.windows-host.xml", dataContext);
            Window timeServiceWindow = (Window)ConsoleApplication.LoadFromXaml("HelloWorld.timeservice.xml", null);

            dataContext.OpenTimeServiceWindowCommand = new RelayCommand(param => windowsHost.Show(timeServiceWindow));

//            windowsHost.Show(timeServiceWindow);
            ConsoleApplication.Instance.Run(windowsHost);
        }


        public class DataContext : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;

            [NotifyPropertyChangedInvocator]
            protected virtual void OnPropertyChanged(string propertyName)
            {
                PropertyChangedEventHandler handler = PropertyChanged;
                if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
            }

            public DataContext()
            {
                ExitCommand = new RelayCommand(param => Environment.Exit(0));
            }

            public ICommand ExitCommand { get; set; }
            public ICommand OpenTimeServiceWindowCommand { get; set; }
     }

ktodyruik avatar Oct 02 '14 20:10 ktodyruik

Did you use OneTime binding mode to bind OpenTimeServiceWindowCommand ? OneTime binding works only when object is being created from xaml. May be you need OneWay binding ? And it is need to raise PropertyChanged when command will be changed.

elw00d avatar Oct 02 '14 21:10 elw00d