How can I let a user of a Windows Universal App swipe from one page to another? (I thought this would be easy to find, but searching hasn’t uncovered the answer.)
And if this is possible within one page - that's fine too. (To swipe one grid out and another in.)
Pivot control behaves like you discribed.
See guidelines for tabs and pivots.
Example:
<Page x:Class="App1.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 Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Pivot>
<PivotItem Header="Item 1" Background="Black" />
<PivotItem Header="Item 2" Background="Red" />
<PivotItem Header="Item 3" Background="Blue" />
</Pivot>
</Grid>
You can use GestureRecognizer and manipulate what you wanna do. Create animation for the FX.
I want to say use a FlipView control, but that could be dangerous if your views are too complex. FlipView will keep your pages rendered and ready to be flipped to at all times. I think you can try to implement your own thing to keep memory usage low. Maybe use a GestureRecognizer so that you have control over where the user can swipe and only render what you need and discard anything obsolete or off the screen.
Pivot will also create this effect, but the difference is that it must completely slide one element off the screen and then slide the next one in. It keeps from having two or three views rendered at once, which is good for memory. However, you won't be able to see both pages sliding in/out at the same time.
Try them both, see which is best for you.
I have something similiar to what you're asking:
How to "swipe" from one page to another:
On page 1 (The page where you will swipe FROM)
Make a grid, and put these values in:
XAML:
<Grid Padding="15,15,15,15"
HorizontalAlignment="Left"
VerticalAlignment="Stretch"
ManipulationMode="TranslateX,TranslateInertia,System"
ManipulationDelta="SwipeablePage_ManipulationDelta"
ManipulationCompleted="SwipeablePage_ManipulationCompleted">
Code Behind:
private bool _isSwiped;
private void SwipeablePage_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
if (e.IsInertial && !_isSwiped)
{
var swipedDistance = e.Cumulative.Translation.X;
if (Math.Abs(swipedDistance) <= 2) return;
if (swipedDistance > 0)
{
// go to next page
this.Frame.Navigate(typeof(Page2));
}
else
{
// do nothing
}
_isSwiped = true;
}
}
Related
I am trying to change the size of a grid using data binding in order to be able to expand certain sections of my UI. I have looked online and nothing really seems to work. My window has a frame that loads a "root page" with another frame inside of it as seen in rootpage.xaml below. I have added a textbox but that does not seem to work. Interestingly enough, when I click the button present on the page. I do get a line outputted so my code is running. Adding a breakpoint shows similar results that the property FullScreenValue does in fact change. I think I am missing something in order to get the PropertyChanged event to be received or I may be unintentionally instancing multiple instances of my ViewModel. Looking for a solution.
My root page loaded into the frame in my window:
<Page
x:Class="MVVM.Views.rootPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MVVM.Views"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:ViewModels="using:MVVM.ViewModels"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.DataContext>
<ViewModels:RootPageViewModel x:Name="ViewModel"/>
</Page.DataContext>
<Grid x:Name="frameGrid" ColumnDefinitions="*, *" RowDefinitions ="*, *" Grid.Row="1" Margin="15, 0, 15, 0" >
<Frame x:Name="topleftFrame" Grid.Column="0" Grid.Row="0" CornerRadius="8" Margin="10, 10, 10, 10" Grid.ColumnSpan="{Binding FullScreenValue,Mode=OneWay}" Grid.RowSpan="{Binding FullScreenValue, Mode=OneWay}"/>
<AppBarButton Icon="FullScreen" Grid.Column="0" Grid.Row="0" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="10,5,5,10" Command="{Binding FullScreenCommand, Mode=OneWay}"/>
Visibility="Visible"/>
<TextBlock Text="{Binding FullScreenValue, Mode=OneWay}" Grid.Row="1" Grid.Column="1"/>
</Grid>
</Page>
My ViewModel:
namespace MVVM.ViewModels
{
public partial class RootPageViewModel : ObservableObject
{
[ObservableProperty]
private int fullScreenValue;
public RootPageViewModel()
{
fullScreenValue = 1;
}
[ICommand]
void FullScreen()
{
fullScreenValue = 2;
Debug.WriteLine("HI");
}
}
}
As you can see I am trying to make use of the community toolkit. I have tried replacing some of these generated snippets with standard mvvm properties and commands to no avail. If I change the constructor to have a value of 2 I get my desired result, but can't seem to do it with this button! Send help.
My desired result is upon clicking the button, the frame will now span 2 columns and 2 rows instead of 1 column and 1 row. Maybe because this sort of UI concerns strictly the view it does not necessarily need a ViewModel but nonetheless I am still looking for help as I feel like I will run into this problem in the future. I am new to a lot of things in the Microsoft ecosystem so please forgive me if this is a repeat question and I just could not understand other answers.
I am making a video game, where each grid serves as game room. Each grid\room has a large number of objects like things that can be used, images and sound files. Until now, they all were stored in one large file. But now, I was told that this approach wastes a lot of resources.
My plan is, to store xaml code of every such grid as a separate file, then load relevant file at run time with usual code.
For now xaml looks about like this:
<Window
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" x:Name="wdwMain" x:Class="RealityIncognita.MainWindow"
Height="900" Width="1600" ResizeMode="NoResize" WindowState="Maximized"
Cursor="Cross" WindowStyle="None" Loaded="wdwMain_Loaded">
<Viewbox Stretch="Fill">
<Grid x:Name="areaContainer" HorizontalAlignment="Left" Height="900"
VerticalAlignment="Top" Width="1600">
<Grid x:Name="areaMain">
<Grid.Background>
<ImageBrush
ImageSource="Resources/Images/Interface/main_interface.jpg"/>
</Grid.Background>
<Grid x:Name="areaShowers" HorizontalAlignment="Left" Height="700"
Margin="1653,790,-1561,-590" VerticalAlignment="Top" Width="1508"
IsVisibleChanged="areaShowers_IsVisibleChanged">
Here's example - areaShowers is a grid for relevant room. Until now, it was stored in the main file, like all other grids, and when I needed, I just altered its Margin to put it upon "areaMain" - also a grid.
Now though, I want to put each room into a file, then load it when I need it, and remove it from memory when I don't.
For example I'll create an empty grid "areaGeneric" and add it and it alone to original xaml.
So, I want something like this. Can't provide any earlier attempt, because I don't really know how it can be done.
Grid new_grid = new Grid;
new_grid = load from file (areaRoom.xaml); (file is among the project's
resources)
areaGeneric = new_grid;
Can I load a grid xaml at run-time, then switch grids in main code?
Thank you,
Evgenie
A really simple solution would just be to house each of your rooms inside a user control and then place the control into your container grid when you need to change rooms. Here's the rough idea:
public partial class MainWindow : Window
{
UserControl _currentRoom;
public MainWindow()
{
InitializeComponent();
}
protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
{
this.areaContainer.Children.Clear();
_currentRoom = null;
if (e.LeftButton == MouseButtonState.Pressed)
_currentRoom = new Room1();
if(e.RightButton == MouseButtonState.Pressed)
_currentRoom = new Room2();
this.areaContainer.Children.Add(_currentRoom);
base.OnPreviewMouseDown(e);
}
}
A "Room":
<UserControl x:Class="Test.Room1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Button Height="100" Width="100">
Hello world!
</Button>
</UserControl>
As for cleaning up your resources - once the user control is removed from the visual tree (assuming you aren't holding a reference) the GC should dispose of the user control. If you wanted to clear your resources more quickly you could implement a dispose method on your rooms and then call that before you change areas.
I have a Windows universal UWP app that I am using Pivot on to give me the ability to swipe from page to page for navigation. Let's say I have three UI pages (page1, page2 and page3), I then have three PivotItems, one for each. The question is, inside of the PivotItem, I currently have a Frame in each and am using the Frame to show the UI page. This is working, however, this seems redundant because as I understand it, a Frame is used to dynamically show content such as a UI. It seems that you would have EITHER buttons or links for the tabs in a grid and then use one frame to rotate the UI views depending on which button is clicked OR you would use pivot, which I am doing. Main reason I chose pivot, I am targeting mobile and I do want to be able to swipe from page to page.
So, what I don't know is, when using pivot, what do I put in each PivotItem? Is a frame on each correct? Or should I use some other item like UIElement?
Thanks!
What I want to know specifically is instead of stuffing controls directly in the PivotItem, how do I just have each PivotItem reference and use my other pages?
Pivot is a ItemsControl.so it can contain a collection of items of any type, including the Page. You can use pages in PivotItem like below:
<Page
x:Class="ProjectName.MainPage"
xmlns:local="using:ProjectName"
...
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Pivot x:Name="rootPivot" Title="Pivot Title">
<PivotItem Header="Pivot Item 1">
<!--reference the page with local:PageName-->
<local:PageOne></local:PageOne>
</PivotItem>
<PivotItem Header="Pivot Item 2">
<local:PageTwo></local:PageTwo>
</PivotItem>
<PivotItem Header="Pivot Item 3">
<local:PageThree></local:PageThree>
</PivotItem>
</Pivot>
</Grid>
What is the SIMPLEST way of implementing list view multiple select scenario together with the AppBar? So that it behaves exactly as the Windows 8 start screen when multiple items selected (e.g. via the mouse right-click).
I want to show the app bar together with the first selected list view item, I want to keep it opened with the second, third and so on and I want to close it either by any app bar button action (context action performed) or by other system wide app bar close action (e.g. right-click somewhere else, which would mean context action cancelled).
My current implementation is too complicated. I believe I must have missed something - such a basic and common scenario must be possible to implement in a standardized way.
Scaffolding code prepared below. If only this code used the app bar hides before right-click on the second list view item and one more right-click on list view is required (not acceptable). If combined with IsSticky it is not possible to select the second list view item at all.
<Page
x:Class="ListViewAndAppBar.ExamplePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ListViewAndAppBar"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
DataContext="{Binding ExamplePageViewModel, Source={StaticResource Locator}}">
<Grid Background="Gray">
<ListView
x:Name="ListView"
ItemsSource="{Binding Persons}"
SelectionMode="Multiple"
SelectionChanged="ListView_SelectionChanged">
</ListView>
</Grid>
<Page.BottomAppBar>
<AppBar x:Name="BottomAppBar" Padding="10,0,10,0">
<Button x:Name="BottomAppBarBack" Tag="Back" Style="{StaticResource BackAppBarButtonStyle}" HorizontalAlignment="Left" />
</AppBar>
</Page.BottomAppBar>
</Page>
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
this.BottomAppBar.IsOpen = true;
//this.BottomAppBar.IsSticky = true;
}
Answering my own question. I found the solution short after I posted the question. I will leave it here in case somebody does the same beginner's mistake.
The solution cannot be simpler: IsSticky must be called BEFORE IsOpen. After this switch all works as expected.
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (this.ListBox.SelectedItems.Count > 0)
{
this.BottomAppBar.IsSticky = true;
this.BottomAppBar.IsOpen = true;
}
else
{
this.BottomAppBar.IsOpen = false;
this.BottomAppBar.IsSticky = false;
}
// Or the following if you wish...
// this.BottomAppBar.IsOpen = this.BottomAppBar.IsSticky = this.ListView.SelectedItems.Count > 0;
}
What would be the best way to build a data-navigation like in access-forms in XAML/C#?
Should I build a user control (or even custom control) that I just bind to my collection in which I can put other controls? (hence this question: C# User Control that can contain other Controls (when using it) )
Or can I build something by deriving from then ItemsControl somehow? how?
Or would this be done completely different today (like "this style of navigation is so last year!")?
I'm relatively new to C# and all (not programming as such, but with more like "housewife-language" Access-VBA) also I'm no native english speaker. So pls be gentle =)
You can create user control and place a bunch of buttons (First, Prev, Next, Last, etc..) in it and place it on the main window. Secondly, you can bind your data navigation user control to a CollectionViewSource which will help you to navigate among your data.
Your main window:
<Window.Resources>
<CollectionViewSource x:Key="items" Source="{Binding}" />
</Window.Resources>
<Grid>
<WpfApplication1:DataNavigation DataContext="{Binding Source={StaticResource items}}" />
<StackPanel>
<TextBox Text="{Binding Source={StaticResource items},Path=Name}" />
</StackPanel>
</Grid>
Your Data Navigation User Control:
<StackPanel>
<Button x:Name="Prev" Click="Prev_Click"><</Button>
<Button x:Name="Next" Click="Next_Click">></Button>
<!-- and so on -->
</StackPanel>
And your click handlers goes like this:
private void Prev_Click(object sender, RoutedEventArgs e)
{
ICollectionView view = CollectionViewSource.GetDefaultView(DataContext);
if (view != null)
{
view.MoveCurrentToPrevious();
}
}
I hope this helps.
Sounds like you're after a DataGrid control. Microsoft is releasing a WPF DataGrid as part of a WPF Toolkit which you can download here: http://wpf.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=25047.