<cms:MenuList ID="TopMenu" AutoBind="True" runat="server">
<HeaderTemplate>
<ul class="navbar-nav ml-auto">
</HeaderTemplate>
<ItemTemplate>
<asp:Panel runat="server" Visible="<%#!Container.CurrentPage.HasChildren %>">
<li class="nav-item">
<a href="<%#Container.CurrentPage.PageUrl %>" class="nav-link"><%#Container.CurrentPage.PageName %></a>
</li>
</asp:Panel>
<asp:Panel runat="server" Visible="<%#Container.CurrentPage.HasChildren %>">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" id="navbarDropdownMenuLink<%#Container.CurrentPage.PageId %>" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><%#Container.CurrentPage.PageName %></a>
<div class="dropdown-menu dropdown-primary" aria-labelledby="navbarDropdownMenuLink<%#Container.CurrentPage.PageId %>">
<cms:MenuList AutoBind="True" DataSource="<%#Container.CurrentPage.Children %>" runat="server">
<ItemTemplate>
<a class="dropdown-item" href="<%#Container.CurrentPage.PageUrl %>"><%#Container.CurrentPage.PageName %></a>
</ItemTemplate>
</cms:MenuList>
</div>
</li>
</asp:Panel>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</cms:MenuList>
There's a bit of a limitation with the above approach; it will select render path based on amount of children and not if those children actually are visible in menu. (This could be worked around by replacing HasChildren with a custom method checking children with show in menu set).