Changing the size of SplitView.Pane - xaml

The basic hamburger menu using SplitView found in many examples is cool but I like the way Microsoft implemented it in some of their apps in Windows 10 such as News and Sports. The way they implemented it is when the SplitView.Pane is open, its height is not the same as the root frame's height. In other word, the Pane's height and Content's height is not the same. The benefit of this style is that full content of the pageheader of the SplitView.Content is visible. Can somebody help me out on how to achieve that effect since I am new to xaml. I hope my question is pretty clear to understand.
Thanks,
AB

On the official "sport"/"news" page, there are several elements: toggle button, SplitView and etc. In the SplitView, there are also several sub-items, such as panel and frame. There are lots of approaches to help you to get your own desired effect: you can use layout panel, such as StackPanel or Grid, to arrange those UI elements on the page; you can modify the splitview's default template; and you can also just customize frame and panel' height by setting their related properties, such as: height or Margin. For more instructions of UWP design please go here.
Below is a simple example by using Grid layout and adjusting "margin" property of splitview's frame. In this example, I put the toggled button and a back button on the page header (you can change the back button to a navigation bar later). Then adjust the "margin" property of the frame, so that it doesn't has the same height as the panel. You can get a complete sample of SplitView here.
<!-- Put the whole page content in a grid of 2*2 -->
<Grid>
<Grid.RowDefinitions >
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions >
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button x:Name="BackButton"
Grid.Row="0"
Grid.Column="1"
HorizontalAlignment="Center"
TabIndex="2"
IsEnabled="{Binding AppFrame.CanGoBack, ElementName=Root}"
Width="{Binding ItemsPanelRoot.Width, ElementName=NavMenuList}"
Click="BackButton_Click"/>
<!-- Top-level navigation menu + app content
and put the SplitView in another row to leave space for page header -->
<SplitView x:Name="RootSplitView"
DisplayMode="Inline"
OpenPaneLength="256"
IsTabStop="False" Grid.Row="1" Grid.ColumnSpan="2">
<SplitView.Pane >
<!-- A custom ListView to display the items in the pane. The automation Name is set in the ContainerContentChanging event. -->
<controls:NavMenuListView x:Name="NavMenuList"
TabIndex="3"
ContainerContentChanging="NavMenuItemContainerContentChanging"
ItemContainerStyle="{StaticResource NavMenuItemContainerStyle}"
ItemTemplate="{StaticResource NavMenuItemTemplate}"
ItemInvoked="NavMenuList_ItemInvoked">
</controls:NavMenuListView>
</SplitView.Pane>
<!-- Set Frame's margin property to differ from panel -->
<!-- OnNavigatingToPage we synchronize the selected item in the nav menu with the current page.
OnNavigatedToPage we move keyboard focus to the first item on the page after it's loaded. -->
<Frame x:Name="frame"
Navigating="OnNavigatingToPage"
Navigated="OnNavigatedToPage"
Margin="0,100,0,0" >
<Frame.ContentTransitions>
<TransitionCollection>
<NavigationThemeTransition>
<NavigationThemeTransition.DefaultNavigationTransitionInfo>
<EntranceNavigationTransitionInfo/>
</NavigationThemeTransition.DefaultNavigationTransitionInfo>
</NavigationThemeTransition>
</TransitionCollection>
</Frame.ContentTransitions>
</Frame>
</SplitView>
<!-- Declared last to have it rendered above everything else, but it needs to be the first item in the tab sequence. -->
<ToggleButton x:Name="TogglePaneButton"
TabIndex="1"
Style="{StaticResource SplitViewTogglePaneButtonStyle}"
IsChecked="{Binding IsPaneOpen, ElementName=RootSplitView, Mode=TwoWay}"
Unchecked="TogglePaneButton_Checked"
AutomationProperties.Name="Menu"
ToolTipService.ToolTip="Menu" Grid.Row="0" Grid.Column="0" />
</Grid>

Related

How do I edit the header of an Expander control in WinUI 3?

When I edit properties of the Expander control, the effects seem to only apply to the content of the Expander, rather than the header.
E.g. if I set the BorderBrush as black and the Background as aquamarine, those properties only apply to the content:
<Expander Header="Expander" BorderBrush="Black" Background="Aquamarine">
<TextBlock Text="Here is some text"/>
</Expander>
See what the above code looks like
I know I can use this syntax:
<Expander>
<Expander.Header>
<!--XAML content here-->
</Expander.Header>
</Expander>
and put XAML content inside the header. So I tried putting a StackPanel in there, and editing the border and background on that—but it only applied to a small portion of the Expander header, and didn't cover the drop down caret, for example.
How do I change properties of the header?
You can edit the default style but this might be easier:
<Border
HorizontalAlignment="Left"
VerticalAlignment="Center"
Background="SkyBlue"
BorderBrush="HotPink"
BorderThickness="1"
CornerRadius="{StaticResource ControlCornerRadius}">
<Expander
Content="CONTENT"
Header="HEADER" />
</Border>
You just need to set the Border's properties.

How to resize NavigationView and SplitView in UWP

I want to enable user to resize the NavigationView in my UWP app. Couldn't find any resources how I could do that.
I see some of the apps have "Resizable splitView" but for SplitView also, I cannot see any such resize property exposed to set by default.
Pls help.
Thanks in Advance
There are no such property can resize SplitView and NavigationView, you need to custom layout to implement a similar effect. You could use Slider control and bind the OpenPaneLength Property of SplitView to Slider.Value to do this. Please refer to the following code.
<Grid>
<SplitView Name="CoreSplitView"
DisplayMode="Inline"
IsPaneOpen="True"
OpenPaneLength="{Binding Value, ElementName=MasterSlider, Mode=OneWay}">
<SplitView.Pane>
<Grid Name="PaneGrid" Background="Gray">
<Slider Name="MasterSlider"
MinWidth="480"
VerticalAlignment="Stretch"
Maximum="480"
Minimum="10"
Opacity="0"
Value="150"
/>
<StackPanel Name="PaneStackPanel"
Margin="0,0,10,0" Background="LightGray">
<TextBlock TextWrapping="Wrap" Text="Use a slider when you want your users to be able to set defined, contiguous values (such as volume or brightness) or a range of discrete values (such as screen resolution settings).A slider is a good choice when you know that users think of the value as a relative quantity" />
</StackPanel>
</Grid>
</SplitView.Pane>
<Grid Name="ContentGrid" Background="LightSteelBlue">
</Grid>
</SplitView>
</Grid>
The StackPanel that is directly under our slider, acts like a cover for our Slider. Notice the StackPanel has Margin="0,0,10,0", this translates to a 10px distance from the right wall, which allows the Slider area to be exposed as a gray strip that is used to drag the Pane, again the 10px is arbitrary but it has to match the Minimum of the Slider.

Reuse large quantity of Xaml interface elements

I have made a very similar post about this earlier where I asked how to reuse a part of some Xaml code. Although that worked for the small element I had, it does not quite work on the current scale.
Using Xamarin, I have a tabbed layout with two pages. A page consists of a grid with three layers, two of which are the same on both pages. The third layer needs to be different on both pages. Both pages are currently in the same file. This means that a large portion of the code is simply a copy-paste, and it makes it more difficult to edit values of certain labels in those first two rows since they can't have similar IDs / Names.
I currently set a string variable in the codebehind with a setter.
string _vesselCode;
public string VesselCode
{
get
{
return _vesselCode;
}
set
{
_vesselCode = value;
currentVessel.Text = _vesselCode;
currentVesselClone.Text = currentVessel.Text;
}
}
Although this works, I still have a lot of duped code (as shown below).
This is the content of each page. The only page-specific content is at the bottom. The rest is literately copy-pasted to the second page. Code below is without any IDs.
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<!-- first row from top {0} - app name, vessel. -->
<RowDefinition Height="Auto"/>
<!-- second row {1} - originele freq // nieuwe frequentie. -->
<RowDefinition Height="Auto"/>
<!-- third row {2} - tablayout. -->
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- header contents -->
<Grid Grid.Row="0" StyleClass="headerBar">
<StackLayout Grid.Column="0" HorizontalOptions="Start" StyleClass="inGrid">
<Label StyleClass="header"
Text="OV Frequentie"/>
<Label StyleClass="headerSub"
Text="huidig voertuig:"/>
</StackLayout>
</Grid>
<!-- freq bar contents -->
<Grid Grid.Row="1" StyleClass="subHeaderBar">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<BoxView Grid.ColumnSpan="2"
BackgroundColor="#2d313a"
WidthRequest="2"
HeightRequest="2"
Margin="5,0,5,-3"/>
<StackLayout Grid.Column="0" HorizontalOptions="Start" StyleClass="inGrid">
<Label StyleClass="generalSmallText"
Text="originele freq: 10"/>
</StackLayout>
<StackLayout Grid.Column="1" HorizontalOptions="End" StyleClass="inGrid">
<Label StyleClass="generalSmallText"
Text="nieuwe freq: 10"/>
</StackLayout>
</Grid>
<!-- info page content -->
<Grid Grid.Row="2">
<StackLayout StyleClass="infoDisplayPage">
<!-- page unique stuff -->
</StackLayout>
</Grid>
</Grid>
Like I said, this sort of works, but is incredibly bad code. There are multiple Labels I want to be able to change the value of, but I can't give them the same ID. This means I have to either always set those values twice, or get some set attribute on one of the Labels, automatically setting the other one / have attributes in the code behind with such setter.
I got told that for using bigger area's of code, I could use a ContentView. However, I can't seem to reuse them across two ContentPages.
How do I make it so I can reuse the code of the first two grid rows on both pages, and be able to have different contents of the third grid layout? I'm OK with having to possibly set both Labels using the codebehind as above if that is needed.
I'm quite new to app development, so any extra source of explenation of the code below is appriciated.

How to fix the ScrollViewer/ListBox height to be the screen height?

I have a Universal Windows Platform application.
I have a ScrollViewer which has a button on the top, a ListBox and a button below the ListBox (I know it is not a good practice to have a ListBox inside a ScrollViewer, but this is not my code and I can't modify the implementation).
The ScrollViewer's VerticalScrollMode and VerticalScrollBarVisibility are both set to false, so it is not possible to scroll vertically (this is also a requirement).
When the ListBox contains many items, the height of the list becomes bigger than the device height. As a result a part of the ListBox and the Buttons below the list are not available (as the vertical scroll is disabled).
<ScrollViewer>
<RelativeLayout>
...
<Button name="Button1">
...
</Button>
<ListBox MinHeight="120">
</ListBox>
<Button name="Button2">
...
</Button>
</RelativeLayout>
</ScrollViewer>
Is there a way to fix the ScrollViewer's height to be the device screen height? And fix the ListBox's height so that the ListBox's height grows only so that the ListBox fits on the space between the Button1 and Button2?
Your problem is not the scrollviewer's height. It is the listbox that expands to accomodate it's contents (as it should). By limiting the listbox's height you can take care of that.
You can use a grid with 3 rows. Something like this
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Button x:Name="ButtonTop" Grid.Row=0/>
<ListView x:Name="DontPutListViewInScrollViewer" Grid.Row=1/>
<Button x:Name="ButtonBottom" Grid.Row=2/>
</Grid>
Notice the Height defined in the middle row. That means that the listview will take all space that the top and bottom row leave available.
Then put this grid in the ScrollViewer.

Horizontal context menu with icons Windows phone 8

I am trying to add a context menu which shows menu items horizontally. My sample code:
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<StackPanel Orientation="Horizontal">
<toolkit:MenuItem Tap="CallMenuItem_tapped">
<toolkit:MenuItem.Header>
<Image Height="50"
Stretch="Uniform"
Source="Assets/icon1.png" />
</toolkit:MenuItem.Header>
</toolkit:MenuItem>
<toolkit:MenuItem Tap="ChatMenuItem_tapped">
<toolkit:MenuItem.Header>
<Image Height="50"
Stretch="Uniform"
Source="Assets/icon2.png" />
</toolkit:MenuItem.Header>
</toolkit:MenuItem>
<toolkit:MenuItem Tap="OtherMenuItem_tapped">
<toolkit:MenuItem.Header>
<Image Height="50"
Stretch="Uniform"
Source="Assets/icon3.png" />
</toolkit:MenuItem.Header>
</toolkit:MenuItem>
</StackPanel>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
I am facing some problems. First of all when I tap a menu item the specific event is called but the menu remains open. As I am showing all the menu items in one line(horizontally), I am unable to fix the height and width of context menu. Is there a better way to add a horizontal context menu using icons?
I would suggest you to use the ItemsPanel property to set the layout as horizontal stack panel. And if you still face any issues then you can manually close the context menu using the IsOpen property. Hope this helps you.