I want to create buttons on my UWP/XAML app similar to the buttons on the Windows 'Settings' page using the WinUI 3 library. The gallery didn't show this kind of button with an icon and a title/description. I'm wondering how it can be accomplished since I am developing an app that mostly serves as a portal to go to websites and navigate easily through web/PC apps. Any help would be appreciated.
I want the buttons to simply redirect the user to a NavigationView page (Page5.xaml)
I have a NavigationView on MainPage.xaml and these buttons are going on Page4, so I'm not sure how I can program the buttons to go to Page5.xaml
https://i.stack.imgur.com/7Uff8.png
You can create a usercontrol and use some of my code:
MyUserControl.xaml:
<Grid x:Name="MainGrid" PointerEntered="Grid_PointerEntered" PointerExited="Grid_PointerExited" PointerPressed="FontIcon_PointerPressed" Margin="20,5,20,5" Height="70" CornerRadius="5" Padding="{StaticResource ExpanderHeaderPadding}" HorizontalAlignment="Stretch" Background="{ThemeResource ExpanderHeaderBackground}" BorderThickness="{ThemeResource ExpanderHeaderBorderThickness}" BorderBrush="{ThemeResource ExpanderHeaderBorderBrush}">
<StackPanel Orientation="Horizontal" Margin="0,20,0,20">
<FontIcon FontFamily="Segoe MDL2 Assets" Glyph="" Margin="0,0,20,0"/>
<TextBlock FontSize="24" VerticalAlignment="Center" HorizontalAlignment="Left" Text="Font"/>
</StackPanel>
<FontIcon FontFamily="Segoe MDL2 Assets" Glyph="" HorizontalAlignment="Right" Margin="0,0,20,0"/>
</Grid>
MyUserControl1.xaml.cs:
public MyUserControl1()
{
this.InitializeComponent();
var color = (MainGrid.Background as SolidColorBrush).Color;
color.A = 20;
MainGrid.Background = new SolidColorBrush(color);
}
private void FontIcon_PointerPressed(object sender, PointerRoutedEventArgs e)
{
if (e.GetCurrentPoint(sender as UIElement).Properties.IsLeftButtonPressed)
{
//Do whatever you want
Debug.WriteLine("Pressed");
}
}
//Change the color on hover:
private void Grid_PointerEntered(object sender, PointerRoutedEventArgs e)
{
var color = (MainGrid.Background as SolidColorBrush).Color;
color.A = 50;
MainGrid.Background = new SolidColorBrush(color);
}
private void Grid_PointerExited(object sender, PointerRoutedEventArgs e)
{
var color = (MainGrid.Background as SolidColorBrush).Color;
color.A = 20;
MainGrid.Background = new SolidColorBrush(color);
}
Related
TeachingTip does not seem Pointer* events have implemented, therefore I had to add a Grid to hero content to get those events fired :
<TeachingTip IsOpen="True" Title="City Village" Subtitle="Legend highlighted in HeroContent">
<TeachingTip.HeroContent>
<Grid PointerMoved="OnPointerMoved" PointerPressed="OnPointerPressed" PointerReleased="OnPointerReleased" PointerCanceled="OnPointerReleased">
<Image Source="ms-appx:///Assets/Qantas.svg" Margin="5"/>
</Grid>
</TeachingTip.HeroContent>
<TeachingTip.Content>
<GridView ItemsSource="{x:Bind ViewModel.Items}" Margin="5">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid Orientation="Horizontal"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemTemplate>
<DataTemplate x:DataType="model:ChartLegendItem">
<StackPanel>
<Line Stroke="{x:Bind Color, Converter={StaticResource HexBrushConverter}}" X1="0" Y1="0" X2="10" Y2="0" StrokeThickness="5"/>
<TextBlock Text="{x:Bind Caption}"/>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</TeachingTip.Content>
</TeachingTip>
Also added the handlers but this is not moving the control :
private void OnPointerPressed(object sender, PointerRoutedEventArgs args)
{
var point = args.GetCurrentPoint(this);
if (point.Properties.IsLeftButtonPressed)
{
_isDragging = true;
_clickPosition = point;
CapturePointer(args.Pointer);
args.Handled = true;
}
}
private void OnPointerReleased(object sender, PointerRoutedEventArgs args)
{
_isDragging = false;
ReleasePointerCapture(args.Pointer);
args.Handled = true;
}
private void OnPointerMoved(object sender, PointerRoutedEventArgs args)
{
if (_isDragging)
{
var currentPosition = args.GetCurrentPoint(this);
if (RenderTransform is not TranslateTransform)
{
RenderTransform = new TranslateTransform();
}
var p = new Point(currentPosition.Position.X, currentPosition.Position.Y);
var p1 = RenderTransform.TransformPoint(p);
args.Handled = true;
}
}
Is it needed to be on a Canvas or the transformation itself is inappropriate ?
In our UWP app the DataTemplate for MyListView is set in the code behind to either DataTemplateA or DataTemplateB in Page.Resources. Each data template contains a grid (TopGrid) which contains a DisplayGridButton and another grid (DisplayGrid).
DisplayGrid contains SecondListView and a HideGridButton
DisplayGridButton should show DisplayGrid. HideGridButton should collapse DisplayGrid.
The XAML is
<Page.Resources>
<DataTemplate x:Key="DataTemplateA">
<Grid Name="TopGrid">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<TextBox/>
<Button Name="DisplayGridButton" Content="Show" Margin="10,0" Click="DisplayGridButton_Click"/>
</StackPanel>
<Grid Name="DisplayGrid" Grid.Row="1" Visibility="Collapsed">
<StackPanel>
<Button Name="HideGridButton" Content="Hide" Click="HideGridButton_Click"/>
<ListView Name="SecondListView">
<ListView.ItemTemplate>
<DataTemplate >
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</Grid>
</Grid>
</DataTemplate>
<DataTemplate x:Key="DataTemplateB">
<Grid Name="TopGrid">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<TextBox/>
<Button Name="DisplayGridButton" Content="Show" Margin="10,0" Click="DisplayGridButton_Click"/>
</StackPanel>
<Grid Name="DisplayGrid" Grid.Row="1" Visibility="Collapsed">
<StackPanel>
<Button Name="HideGridButton" Content="Hide" Click="HideGridButton_Click"/>
<ListView Name="SecondListView">
<ListView.ItemTemplate>
<DataTemplate >
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</Grid>
</Grid>
</DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ListView Name="MyListView">
</ListView>
</Grid>
DataTemplateA or DataTemplateB is set in the code behind.
if (condition)
{
MyListView.ItemTemplate = (DataTemplate)Resources["DataTemplateA"];
}
else
{
MyListView.ItemTemplate = (DataTemplate)Resources["DataTemplateB"];
}
In the Code behind I can create the event handler but I cannot access the DisplayGrid to make it visible or to collapse it.
I would normally set visibility like this.
private void DisplayGridButton_Click(object sender, RoutedEventArgs e)
{
DisplayGrid.Visibility = Visibility.Visible;
}
private void HideGridButton_Click(object sender, RoutedEventArgs e)
{
DisplayGrid.Visibility = Visibility.Collapsed;
}
How do I access the DisplayGrid in the DataTemplate from the button click events?
Since the grid is defined in a template, you'll have to dig it out at runtime. (If you could reference it as "DisplayGrid" from code-behind, you wouldn't know which listview item it belonged to anyway.)
Implement click handlers something like this:
private void DisplayGridButton_Click(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
StackPanel stackPanel = button?.Parent as StackPanel;
Grid grid = stackPanel?.Parent as Grid;
if (grid != null)
{
Grid displayGrid = FindVisualChild<Grid>(grid, "DisplayGrid");
if (displayGrid != null)
{
displayGrid.Visibility = Visibility.Visible;
}
}
}
private void HideGridButton_Click(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
StackPanel stackPanel = button?.Parent as StackPanel;
Grid grid = stackPanel?.Parent as Grid;
if (grid != null)
{
grid.Visibility = Visibility.Collapsed;
}
}
(Fair warning: The way this code finds the appropriate parent to start from is a bit brittle; it might break if the template changes. Searching by name would be better, but I don't have anything handy right now.)
Here is the helper method that finds a named child in the visual tree:
public static T FindVisualChild<T>(
DependencyObject parent,
string name = null)
where T : DependencyObject
{
if (parent != null)
{
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
T candidate = child as T;
if (candidate != null)
{
if (name == null)
{
return candidate;
}
FrameworkElement element = candidate as FrameworkElement;
if (name == element?.Name)
{
return candidate;
}
}
T childOfChild = FindVisualChild<T>(child, name);
if (childOfChild != null)
{
return childOfChild;
}
}
}
return default(T);
}
(This method can also search by type only; just pass null as the name.)
I have the following XAML code for Windows Phone 8.1 (non SilverLight):
<Grid>
<ToggleButton Name="TogBtn" VerticalAlignment="Center" HorizontalAlignment="Center" Checked="ToggleButton_OnChecked">
<SymbolIcon Symbol="play"></SymbolIcon>
</ToggleButton>
</Grid>
The output of the above code is:
How can I change the icon to a stop icon when the toggle button is checked and then back to play icon when unchecked?
I thought this would be easy to find through Google, but apparently not.
Please change your XAML to this:
<Grid>
<ToggleButton x:Name="TogBtn" HorizontalAlignment="Center" VerticalAlignment="Center" Checked="ToggleButton_Checked" Unchecked="ToggleButton_Unchecked">
<SymbolIcon Symbol="Play"></SymbolIcon>
</ToggleButton>
</Grid>
And please add this to your .cs file:
private void ToggleButton_Checked(object sender, RoutedEventArgs e)
{
TogBtn.Content = new SymbolIcon(Symbol.Stop);
}
private void ToggleButton_Unchecked(object sender, RoutedEventArgs e)
{
TogBtn.Content = new SymbolIcon(Symbol.Play);
}
That should do the job!
I have an image control in my main page and the code is as follows:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel HorizontalAlignment="Left" Height="597" VerticalAlignment="Top" Width="440">
<Image x:Name="hinh1" Height="488" Stretch="Fill"/>
<ProgressBar Name="loading" Height="10" IsIndeterminate="True" Visibility="Collapsed"/>
</StackPanel>
</Grid>
and in code behind i have this code :
Uri hinh = new Uri
("http://taigamejar.net/wp-content/uploads/2014/01/Hinh-Anh-Dep-5.jpg", UriKind.Absolute);
hinh1.Source = new BitmapImage(hinh);
While waiting for the image to load, I want to call progress bar run to inform the user that it is loading. Once the the image has loaded, the progress bar should disappear. How can I do this?
If I were you, I would prefer to use , not ProgressBar.
So, I'll give
protected override void OnNavigatedTo(NavigationEventArgs e)
{
loading.IsActive = true;
Uri hinh = new Uri
("http://taigamejar.net/wp-content/uploads/2014/01/Hinh-Anh-Dep-5.jpg", UriKind.Absolute);
hinh1.Source = new BitmapImage(hinh);
hinh1.ImageOpened+=hinh1_ImageOpened; //loadingbar will be disappear when this triggered
}
private void hinh1_ImageOpened(object sender, RoutedEventArgs e)
{
loading.IsActive = false; //this will disable the progressring.
}
And XAML:
<StackPanel HorizontalAlignment="Left" Height="597" VerticalAlignment="Top" Width="400">
<Image x:Name="hinh1" Height="488" Stretch="Fill" ImageOpened="hinh1_ImageOpened"/>
<ProgressRing Name="loading" Height="109" IsActive="True" />
</StackPanel>
If you don't have WP8.1 SDK yet, you can get ProgressRing here: http://www.onurtirpan.com/onur-tirpan/english/windows-phone-english/using-progressring-in-windows-phone/
I'm using a progress bar in my app, this progress bar is defined inside the user control, e.g.:
UserControl x:Class="StirLibrary.ProgressBarControl"
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"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
mc:Ignorable="d" d:DesignHeight="800" d:DesignWidth="480">
<Grid x:Name="LayoutRoot" Height="800">
<Border BorderThickness="2" BorderBrush="Transparent" Background="Transparent" Margin="50,522,50,158">
<StackPanel>
<TextBlock Text="Loading..." Name="loading" Grid.Row="1" HorizontalAlignment="Center" Height="30" Foreground="Green">
</TextBlock>
<ProgressBar Background="Transparent" Margin="10, 0, 0, 10" Height="80" HorizontalAlignment="Center" Name="progressBar1" VerticalAlignment="Top" Width="380" Grid.Row="2" HorizontalContentAlignment="Left" IsHitTestVisible="True" VerticalContentAlignment="Top" Value="0" Maximum="100">
</ProgressBar>
</StackPanel>
</Border>
</Grid>
</UserControl>
My problem is when the orientation of my app changes to landscape the progress bar's orientation doesn't change and this makes the app look ugly. Any suggestions how to avoid this and make the progress bar displayed as per orientation are welcome.
As Matt has mentioned above it is not possible to orient a pop up in user control because User control doesn't have any room for supported orientation. but since it was very crucial requirement for our App i found a work around and made few changes in the Main Page's class file and the user control's class file.. the changes are:
private void PhoneApplicationPage_OrientationChanged(object sender, OrientationChangedEventArgs e)
{
if ((e.Orientation & PageOrientation.Portrait) == PageOrientation.Portrait)
{
ProgressBarControl.getInstance().ProgressBarControl_LayoutUpdated(this, e,e.Orientation.ToString());
}
else if ((e.Orientation & PageOrientation.Landscape) == PageOrientation.Landscape)
{
ProgressBarControl.getInstance().ProgressBarControl_LayoutUpdated(this, e, e.Orientation.ToString());
}
}
These are the changes in MainPage.xaml.cs
public partial class ProgressBarControl : UserControl
{
private static ProgressBarControl instance = null;
public static Popup popup;
private ProgressBarControl()
{
InitializeComponent();
}
public static ProgressBarControl getInstance()
{
if (instance == null)
{
instance = new ProgressBarControl();
popup = new Popup();
popup.Child = instance;
popup.IsOpen = false;
}
return instance;
}
public void ProgressBarControl_LayoutUpdated(object sender, EventArgs e,string orientation)
{
if (orientation == "LandscapeRight")
{
ProgressPanel.RenderTransformOrigin = new Point(0.5, 0.5);
ProgressPanel.RenderTransform = new CompositeTransform { Rotation = 270 };
}
else if(orientation == "LandscapeLeft")
{
ProgressPanel.RenderTransformOrigin = new Point(0.5, 0.5);
ProgressPanel.RenderTransform = new CompositeTransform { Rotation = 90 };
}
else
{
ProgressPanel.RenderTransformOrigin = new Point(0, 0);
ProgressPanel.RenderTransform = new CompositeTransform { Rotation = 0 };
}
}
public static void displayProgressBar(int requestId, int status, string msg)
{
System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
{
if (instance == null)
{
instance = new ProgressBarControl();
popup = new Popup();
popup.Child = instance;
}
popup.IsOpen = true;
instance.loading.Text = msg;
instance.progressBar1.IsIndeterminate = true;
instance.progressBar1.Value = status;
});
}
public static void dismissProgressBar()
{
System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
{
if(popup!=null)
{
popup.IsOpen = false;
}
});
}
}
and this what i have done in my ProgressBarControl.cs file (this is the user control's class file)
Xaml file:
<UserControl x:Class="StirLibrary.ProgressBarControl"
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"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
mc:Ignorable="d" d:DesignHeight="800" d:DesignWidth="480">
<Grid x:Name="LayoutRoot" Height="800">
<!--<Border BorderThickness="2" BorderBrush="Black" Background="Transparent" Margin="54,406,50,320"></Border>-->
<StackPanel x:Name="ProgressPanel" Background="Black" Margin="54,406,50,320">
<TextBlock Text="Loading..." Name="loading" Grid.Row="1" HorizontalAlignment="Center" Height="32" Foreground="White"></TextBlock>
<ProgressBar Background="Green" Margin="10, 0, 0, 10" Height="33" Foreground="White" HorizontalAlignment="Center" Name="progressBar1" VerticalAlignment="Top" Width="351" Grid.Row="2" HorizontalContentAlignment="Left" IsHitTestVisible="True" VerticalContentAlignment="Top" Value="0" Maximum="100"></ProgressBar>
</StackPanel>
</Grid>
</UserControl>
I could enable the orientation for my popup UserControl by simply adding to the Children of the main screen on top of which the Popup is being displayed as:
popUp = new Popup();
loginControl = new LoginPopup(); // this is the custom UserControl
popUp.Child = loginControl;
LayoutRoot.Children.Add(popUp);
The Popup class does not support orientation so you can't use this and expect it to handle orientation changes. This is regardless of whether the control displayed in the popup is in the same assembly or not.
Instead of using a Popup a simple alternative would be to put the control directly on top of all other content on the page. You could include this inside another control (such as a grid or a panel) if you wish.
Manually adding a RotateTransform to the control will give you the ability to add extra control over adjusting the orientation but I'd recommend not going down this route if you can avoid it.