I've been trying to implement Microsoft's hamburger pattern in my own way for some time.
Final result was the following:
AppShell for containing current page and hamburger menu (menu always visible)
In Appshell, Grid with two rows: one 48px in height, one one-start height.
In first row, added a commandbar (global), and hamburger button (togglebutton with custom style for being 48px wide and tall, with the hamburger fonticon in the center)
In second row, SplitView with a ListBox on the Pane, and a Frame in the Content.
This way one has control over the content, while displaying a global menu and command bar. On the Navigated event of the Frame, I update the CommandBar to pull the primary and secondary commands from the Frame's Content's properties (I use a custom page control with those properties), and the content of the CommandBar (which is, of now, a single TextBlock with binding).
However, I wanted to move the ToggleButton into the CommandBar. It worked nicely, except the binding (IsChecked of ToggleButton is bound to IsPaneOpen of SplitView) does not work. I use the regular ElementName targeting, and would prefer to not to use a ViewModel property.
Does the CommandBar.Content use a different context? Or why doesn't the ElementName reference work?
Only way, how I was able to bind to AppBarToggleButton was to set the DataContext in the code behind.
XAML:
<Page.BottomAppBar>
<CommandBar x:Name="CommandBar">
<AppBarToggleButton x:Name="Button" IsChecked="{Binding IsPaneOpen, Mode=TwoWay}" Icon="Home" Label="Button"/>
</CommandBar>
</Page.BottomAppBar>
Code behind:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
Button.DataContext = SplitView;
}
This works for me:
<Page
x:Class="StackOverflowTests.MainPage"
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">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="48"/>
<RowDefinition/>
</Grid.RowDefinitions>
<CommandBar>
<CommandBar.Content>
<AppBarToggleButton Icon="Globe" IsChecked="{Binding ElementName=SplitView,Path=IsPaneOpen,Mode=TwoWay}"/>
</CommandBar.Content>
</CommandBar>
<SplitView Grid.Row="1" Name="SplitView" IsPaneOpen="{x:Bind Appbarbutton.IsChecked.Value,Mode=OneWay}">
<SplitView.Pane>
<ListBox>
<ListBoxItem>Foo</ListBoxItem>
<ListBoxItem>Bar</ListBoxItem>
</ListBox>
</SplitView.Pane>
<SplitView.Content>
<TextBlock>stuff here</TextBlock>
</SplitView.Content>
</SplitView>
</Grid>
<Page.BottomAppBar>
<CommandBar>
<CommandBar.Content>
<AppBarToggleButton Name="Appbarbutton" Icon="Home" />
</CommandBar.Content>
</CommandBar>
</Page.BottomAppBar>
</Page>
You have bind DataContext:
Example:
<Page.BottomAppBar >
<CommandBar x:Name="commandBar" DataContext="{Binding}">
<CommandBar.Content>
<StackPanel Margin="0,0">
<ListView ItemsSource="{Binding Confirmation.AvailableValues}" ItemContainerStyle="{StaticResource ListViewItemBase}">
<ListView.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Value.DisplayName}" Command="{Binding DataContext.Confirm, ElementName=commandBar}" CommandParameter="{Binding Value}" HorizontalAlignment="Center"></Button>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Line Margin="5" X1="0" X2="1000" Y1="0" Y2="0" HorizontalAlignment="Stretch" Height="2" Stroke="#888888" StrokeThickness="1" ></Line>
</StackPanel>
</CommandBar.Content>
</CommandBar>
</Page.BottomAppBar>
Related
Is installed the Fall update and tried out the Navigation View control. Seems close enough to the Hamburger control from the UWP toolkit.
But i am having trouble adding a custom app title to the page. The directions in the article are kinda unclear to me:
Drawing into the title bar has the side-effect of hiding your app's title. To help users, restore the title by adding your own TextBlock. Add the following markup to the root page containing your NavigationView.
This is followed by this xaml:
<!-- Page attribute -->
xmlns:appmodel="using:Windows.ApplicationModel"
<TextBlock x:Name="AppTitle" Style="{StaticResource CaptionTextBlockStyle}" Text="{x:Bind appmodel:Package.Current.DisplayName}" IsHitTestVisible="False"/>
So i thought i'd drop this XAML code inside my Pages grid, but i don't get an App Title. Where do i need to drop this code to make it work?
Heres my page xaml
<Page
x:Class="MyPage"
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"
xmlns:appmodel="using:Windows.ApplicationModel"
mc:Ignorable="d">
<Grid>
<TextBlock x:Name="AppTitle" Style="{StaticResource CaptionTextBlockStyle}" Text="{x:Bind appmodel:Package.Current.DisplayName}" IsHitTestVisible="False"/>
<NavigationView>
<Frame x:Name="ContentFrame" Margin="24">
<ContentControl />
</Frame>
</NavigationView>
</Grid>
</Page>
Your TextBlock is hidden behind your NavigationView. This is more obvious if you have a long enough title that it extends past the Nav Pane:
You can put it on top by switching the order in Xaml:
<Grid>
<NavigationView>
<Frame x:Name="ContentFrame" Margin="24">
<ContentControl />
</Frame>
</NavigationView>
<TextBlock x:Name="AppTitle" Style="{StaticResource CaptionTextBlockStyle}" Text="{x:Bind appmodel:Package.Current.DisplayName}" IsHitTestVisible="False"/>
</Grid>
In my WP 8.1 app I have the MapControl:
<Maps:MapControl x:Name="mapControl" ZoomLevelChanged="mapControl_ZoomLevelChanged" Grid.ColumnSpan="2" Grid.Column="0" Grid.Row="1">
<Maps:MapItemsControl x:Name="MapIcons" ItemsSource="{Binding}" >
<Maps:MapItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Tapped="myStack_Tapped" Maps:MapControl.Location="{Binding GeoPoint}" Maps:MapControl.NormalizedAnchorPoint="{Binding Anchor}">
<Grid x:Name="contentGrid" Background="White" Height="150" Width="220" Visibility="Collapsed"/>
<Image x:Name="myImage" Source="{Binding MapMarker}"/>
</StackPanel>
</DataTemplate>
</Maps:MapItemsControl.ItemTemplate>
</Maps:MapItemsControl>
</Maps:MapControl>
On the map I got markers, and when I click one of them, "contentGrid" apears. The code for that behavior:
private void myStack_Tapped(object sender, TappedRoutedEventArgs e)
{
StackPanel s = sender as StackPanel;
Grid contentBox = s.FindName("contentGrid") as Grid;
contentBox.Visibility = Visibility.Visible;
}
I want to see "contentGrid" always above other markers, but some of them are above my "contentGrid". I tried to set Canvas.Zindex property in XAML in "contentGrid", but it's not working.
I attach screenshot to exemplify my problem.
The StackPanel stacks vertically (by default) or horizontally.
If you want children of the StackPanel in "different layers",
you 'd better replace the StackPanel of the DataTemplate with a Grid or Canvas
A simple solution is to
<DataTemplate>
<Grid Tapped="myStack_Tapped" Maps:MapControl.Location="{Binding GeoPoint}" Maps:MapControl.NormalizedAnchorPoint="{Binding Anchor}">
<Image x:Name="myImage" Source="{Binding MapMarker}"/>
<Grid x:Name="contentGrid" Background="White" Height="150" Width="220" Visibility="Collapsed"/>
</Grid>
</DataTemplate>
Writing the Image in the XAML before the Grid puts it under graphically.
Last, you can play with the ZIndex if you add other controls are added to the Grid/Canvas.
Otherwise I am not sure the ZIndex is really necessaray
EDIT
Canvas.ZIndex is an attached property of Canvas.
But surprisingly it works with the Grid !
The greater Zindex is, the closer the control to your eye (over the other controls)
Regards
Is there any XAML element that will automatically wrap to a new line for sub elements that don't have enough room on a line?
What I mean is that on a wide screen I'll get:
Box1 Box2 Box3
And on a narrow one:
Box1 Box2
Box3
Without having to listen to events and fix it by code.
The comments mention VariableSizedWrapGrid as a solution. But I can't figure out how to make it wrap.
You can use a simple GridView to do it. If you don't set a Height, it should work like a charm.
<GridView Name="xConcerts" ItemsSource="{x:Bind Artist.UpcomingEvents, Mode=OneWay}">
<GridView.ItemTemplate>
<DataTemplate x:DataType="songkick:EventExt">
<Border CornerRadius="8" Background="{ThemeResource ThemeGrayHighColorBrush}" Opacity="0.8">
<StackPanel Margin="18,2">
<TextBlock Text="{x:Bind FullDisplayDate, Converter={StaticResource FormatStringToDateDayConverter}}" Style="{ThemeResource ThemeDateBoldStyle}"/>
<TextBlock Text="{x:Bind FullDisplayDate, Converter={StaticResource FormatStringToDateMonthConverter}}" Style="{ThemeResource ThemeDateBoldStyle}" Margin="0,-4,0,0"/>
</StackPanel>
</Border>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemContainerTransitions>
<TransitionCollection>
<RepositionThemeTransition/>
</TransitionCollection>
</GridView.ItemContainerTransitions>
</GridView>
According to your requirement, using the WrapPanel control in WinRTXamlToolkit will meet your needs.
Sample code here:
<Page x:Class="TestDemo.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Tool="using:WinRTXamlToolkit.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:TestDemo"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Tool:WrapPanel>
<Button Width="200" Margin="10">1</Button>
<Button Width="200" Margin="10">2</Button>
<Button Width="200" Margin="10">3</Button>
</Tool:WrapPanel>
</Page>
And the output here:
So, this may seem rather basic, but so far, the only method I've found in C# for switching the current page in windows universal app is to use the header clicked method combined with setting the IsHeaderInteractive to true. this doesn't look or feel very intuitive considering it just sticks in the little "see more" button that you click on. Rather, how would I go about adding a click event to the entire hub section that changes the page. Here's what I have right now.
private void HubSection_Click(object sender, HubSectionHeaderClickEventArgs e)
{
switch (e.Section.Name)
{
case "China":
Frame.Navigate(typeof(SubtopicPage));
break;
case "Japan":
Frame.Navigate(typeof(SubtopicPage));
break;
}
}
here's the XAML as well:
<Page
x:Class="TestApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource SystemControlForegroundBaseHighBrush}">
<Hub Header="Countries App" Foreground="#FFC3BFBF" SectionHeaderClick="HubSection_Click" Name="CountryHub">
<HubSection x:Name="China" MinWidth="256" Height="460" Background="#FF343434" Header="China" IsHeaderInteractive="True">
<DataTemplate>
<Grid Height="460" Width="256" VerticalAlignment="Bottom">
<Image Source="Assets/chinaFlag.bmp"/>
</Grid>
</DataTemplate>
</HubSection>
<HubSection x:Name ="Japan" MinWidth="256" Height="460" Background="#FF565454" Header="Japan" IsHeaderInteractive="True">
<DataTemplate>
<Grid Height="460" Width="256" VerticalAlignment="Bottom">
<Image Source="Assets/japanFlag.bmp" Height="169"/>
</Grid>
</DataTemplate>
</HubSection>
<HubSection Width="256" Height="460" Background="#FF343434">
</HubSection>
<HubSection Width="256" Height="460" Background="#FF565454">
<DataTemplate>
<Grid Height="460" Width="256" VerticalAlignment="Bottom"/>
</DataTemplate>
</HubSection>
</Hub>
</Grid>
currently two of the four hub sections don't have content, but that's beside the point. Thanks for the help in advance.
Agree with RicardoPons, as I known there is no method to get selected item.
As a work round, You can add Tabbed event of the HubSection. You can know which HubSection was tapped.
For example:
<Hub Header="Countries App" Foreground="#FFC3BFBF" SectionHeaderClick="HubSection_Click" Name="CountryHub">
<HubSection x:Name="China" MinWidth="256" Height="460" Background="#FF343434" Header="China" IsHeaderInteractive="True" Tapped="{x:Bind HubSectionTapped}">
<DataTemplate>
<Grid Height="460" Width="256" VerticalAlignment="Bottom">
<Image Source="Assets/dog.jpg" />
</Grid>
</DataTemplate>
</HubSection>
<HubSection x:Name ="Japan" MinWidth="256" Height="460" Background="#FF565454" Header="Japan" IsHeaderInteractive="True" Tapped="{x:Bind HubSectionTapped}">
<DataTemplate>
<Grid Height="460" Width="256" VerticalAlignment="Bottom">
<Image Source="Assets/color.jpg" Height="169" />
</Grid>
</DataTemplate>
</HubSection>
</Hub>
In code behind:
private void HubSectionTapped(object sender, TappedRoutedEventArgs e)
{
var hubSectiona = sender as HubSection;
var name = hubSectiona.Name;
NaviagteMethod(name);
}
public void NaviagteMethod(string name)
{
switch (name)
{
case "China":
Frame.Navigate(typeof(SubtopicPage));
break;
case "Japan":
Frame.Navigate(typeof(SubtopicPage));
break;
}
}
I think for now it is the only way.
I read the official article in MSDN documentation it seems there is not an event or property to get the current selected item.
https://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.ui.xaml.controls.hub.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1
I have the layout code below in xaml
<Grid>
<StackPanel x:Name="TestStackPanel" Grid.Row="2" Orientation="Horizontal">
<ScrollViewer x:Name="TestScrollViewer" Height="300" VerticalScrollBarVisibility="Auto">
<GridView x:Name="TestGridView"
Width="940"
Background="{StaticResource ApplicationPageBackgroundThemeBrush}"
ItemTemplate="{StaticResource TestTemplate}"
ItemsPanel="{StaticResource TestItemPanelTemplate}"
ItemContainerStyle="{StaticResource TestItemStyle}"
SelectionMode="None"
HorizontalAlignment="Left"/>
</ScrollViewer>
<Button x:Name="TestButton" Content="ClickMe" VerticalAlignment="Bottom" Margin="10,5,0,0" Click="TestButton_Click"/>
</StackPanel>
</Grid>
This displays well in 1366*768 resolution, but if I change the resolution to 2560*1400, it couldn't displays as expected, I know it's certain, but how to adpat the layout to different resolutions? I have tried to add a ViewBox to encapsulate the Grid, it works well in FullScreenLandScape view, but when I change the app to Snap view, the Grid displays in a samll space.
Anyone can help?
Register to the LayoutUpdated event at the UI element.
And re-calculate the layout according to Window.Current.Bounds.Width.