I have a simple UWP app defined as follows:
using System;
using System.Diagnostics;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace SizeChangedBug
{
public sealed partial class MainPage : Page
{
public MainPage() {
this.InitializeComponent();
this.Rectangle.SizeChanged += Rectangle_SizeChanged;
}
private void Rectangle_SizeChanged(object sender, SizeChangedEventArgs e) {
Debug.WriteLine("Rectangle_SizeChanged");
}
}
}
<Page
x:Class="SizeChangedBug.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:SizeChangedBug"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Canvas>
<Slider x:Name="Slider" Orientation="Vertical" Width="80" Height="300" Value="400" Minimum="0" Maximum="600" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<Rectangle x:Name="Rectangle" Margin="200,200" Width="{Binding Value, ElementName=Slider}" Height="{Binding Value, ElementName=Slider}" Fill="Red" HorizontalAlignment="Left" VerticalAlignment="Top"/>
</Canvas>
</Page>
The problem is that SizeChanged never fires and Rectangle_SizeChanged never gets called when the size of Rectangle changes. Am i missing something or it's a bug in UWP? The below XAML with Canvas replaced with Grid works.
<Page
x:Class="SizeChangedBug.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:SizeChangedBug"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<Slider x:Name="Slider" Orientation="Vertical" Width="80" Height="300" Value="400" Minimum="0" Maximum="600" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<Rectangle x:Name="Rectangle" Margin="200,200" Width="{Binding Value, ElementName=Slider}" Height="{Binding Value, ElementName=Slider}" Fill="Red" HorizontalAlignment="Left" VerticalAlignment="Top"/>
</Grid>
</Page>
Canvas uses absolute positioning as its layout technique for its contained child elements. So SizeChanged event of the child will not trigger. It doesn't consider sizing or scaling. it depends on x,y coordinates. I am quoting exact lines from Microsoft document.
https://learn.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.canvas#remarks
Because absolute positioning does not take into account the size of
the app window, scaling, or other user-selected sizing, using a
container element that adapts to different orientations and screen
settings, such as Grid or StackPanel, is often a better choice than
using Canvas.
You can read more about it in Layout Panels
Related
Is there a way to add semi transparent layer for the application in UWP?
In normal .NET there is a possibility, but in UWP I cant find it.
I need this behavior, for make the whole application inactive except one control, and display a tooltip next to the control. It is need for tuturial in application
Thanks for everyone!
I'm imagining you need some sort of BlockUI/UnBlockUI behavior, not sure if there's a 3rd party for that, but you can be creative in order to achieve that.
By taking advantage of ZIndex, Opacity, DependencyProperty and some event handling, you can achieve that.
xaml
<Page x:Name="root"
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
d:DesignHeight="450" d:DesignWidth="800">
<Canvas Background="AliceBlue">
<Rectangle Canvas.Left="30" Canvas.ZIndex="{Binding BlockerZIndex, ElementName=root}" Width="180" Height="200" Fill="White" Opacity="0.5"/>
<Button Canvas.ZIndex="1" Canvas.Left="30" Canvas.Top="70" Content="Send Email" Width="150" Height="50" Background="Blue" Foreground="Black" />
<Button Canvas.ZIndex="1" Canvas.Left="30" Canvas.Top="140" Content="Print Receipt" Width="150" Height="50" Background="Blue" Foreground="Black" />
<Button x:Name="BlockUnBlockUIButton" Canvas.Left="30" Canvas.ZIndex="1" Canvas.Top="210" Width="150" Height="50" Background="Blue" Foreground="Black" Click="BlockUnBlockUIButton_OnClick" >
<TextBlock Text="Block/UnBlock UI" ToolTipService.ToolTip="Block/Unblock UI"/>
</Button>
</Canvas>
</Page>
code-behind
using Windows.UI.Xaml;
namespace App1
{
public sealed partial class MainPage
{
public MainPage()
{
InitializeComponent();
}
public static readonly DependencyProperty BlockerZIndexProperty =
DependencyProperty.Register(
nameof(BlockerZIndex),
typeof(int),
typeof(MainPage),
new PropertyMetadata(2));
public int BlockerZIndex
{
get => (int)GetValue(BlockerZIndexProperty);
set => SetValue(BlockerZIndexProperty, value);
}
private void BlockUnBlockUIButton_OnClick(object sender, RoutedEventArgs e)
{
BlockerZIndex = BlockerZIndex == 1 ? 2 : 1;
}
}
}
I've created a UserControl that contains a ScrollViewer, a StackPanel and two buttons. I've disabled the horizontal scroll bar and want to use the buttons to scroll. But when I set HorizontalSnapPointsType inside of the control it doesn't work. If I add the ScrollViewer directly into my main xaml the property is set. The other properties like HorizontalScrollBarVisibility and HorizontalScrollMode are set properly so I'm not sure what the issue is. I've included xaml below.
<UserControl
x:Class="TestApp.Controls.CarouselScrollViewer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestApp.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid>
<ScrollViewer x:Name="ScrollViewer"
HorizontalScrollBarVisibility="Hidden"
HorizontalScrollMode="Disabled"
VerticalScrollBarVisibility="Hidden"
VerticalScrollMode="Disabled"
HorizontalSnapPointsType="Mandatory">
<ContentPresenter x:Name="Content" Content="{x:Bind ScrollViewerContent}" />
</ScrollViewer>
<Button VerticalAlignment="Center" HorizontalAlignment="Left" Content="LEFT" Background="White" Click="LeftButton_OnClick" Name="BtnLeft"/>
<Button VerticalAlignment="Center" HorizontalAlignment="Right" Content="RIGHT" Background="White" Click="RightButton_OnClick" Name="BtnRight"/>
</Grid>
And then the xaml that's calling the control.
<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:controls="using:TestApp.Controls"
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}">
<controls:CarouselScrollViewer SegmentWidth="400">
<controls:CarouselScrollViewer.ScrollViewerContent>
<StackPanel Orientation="Horizontal">
<Image Source="Assets/cole_anne.png" Height="300" Width="400" Stretch="UniformToFill" Margin="5" />
<Image Source="Assets/icecream.JPG" Height="300" Width="400" Stretch="UniformToFill" Margin="5" />
<Image Source="Assets/jibby_hotdog.png" Height="300" Width="400" Stretch="UniformToFill" Margin="5" />
<Image Source="Assets/andy_courtney_norah.png" Height="300" Width="400" Stretch="UniformToFill" Margin="5" />
<Image Source="Assets/boating.JPG" Height="300" Width="400" Stretch="UniformToFill" Margin="5" />
<Image Source="Assets/dev.jpg" Height="300" Width="400" Stretch="UniformToFill" Margin="5" />
<Image Source="Assets/moir_crab.jpg" Height="300" Width="400" Stretch="UniformToFill" Margin="5" />
<Image Source="Assets/MoirJudLindsayIlgaboating.jpg" Height="300" Width="400" Stretch="UniformToFill" Margin="5" />
</StackPanel>
</controls:CarouselScrollViewer.ScrollViewerContent>
</controls:CarouselScrollViewer>
</Grid>
ScrollViewer.HorizontalSnapPointsType property declares how manipulation behavior reacts to the snap points along the horizontal axis. And as it is declared in the Remarks, this property works for panning actions:
For panning actions, there are often natural stopping places. Snap points provide a way to indicate where these places are. Then, when a user swipes, the manipulation result favors that natural point using behavior as expressed by a SnapPointsType value.
More specifically, this property applies in Touch mode. Ref the "Panning behaviors" section of Guidelines for panning:
Panning with the swipe gesture introduces inertia behavior into the interaction when the touch contact is lifted. With inertia, the content continues to pan until some distance threshold is reached without direct input from the user. Use snap points to modify this inertia behavior.
However, in you code, you've disabled horizontal scroll and used buttons to scroll, so snap points won't work and setting HorizontalSnapPointsType property won't have any effect.
First of all it's my first day using Xaml so this question might be dummy for you, but i totally got lost.
Overview
My technique is that i have MainWindow.xaml and it's split into three areas (using grid columns) the columns width being set automatically.
Based on some actions in the right column, the middle column with show a page let's say Page.xaml that exists in different namespace.
What i'm seeking for
The problem is i need to set the width and height for this page to be equal the middle column width and height as it will fit this area.
Notes
I have very small experience with xaml and binding techniques.
MainWindow.Xaml
<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"
WindowState="Maximized"
ResizeMode="NoResize"
WindowStartupLocation="CenterScreen"
Title="MainWindow" d:DesignWidth="1366" d:DesignHeight="768">
<Grid x:Name="MainGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1.2*" x:Name="LeftColoumn" />
<ColumnDefinition Width="3*" x:Name="CenterColoumn" />
<ColumnDefinition Width=".8*" x:Name="RightColoumn" />
</Grid.ColumnDefinitions>
<ScrollViewer Grid.Column="2">
<StackPanel Orientation="Vertical" x:Name="RightStackPanel" Background="LightGray" >
<Border BorderBrush="{x:Null}" Height="50" >
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" TextWrapping="Wrap" FontWeight="SemiBold" FontStyle="Normal" Margin="3" FontSize="20" >Others</TextBlock>
</Border>
<Expander x:Name="Expander1" Header="Others" Margin="0,0,10,0">
<Button Margin="0,0,0,0" Width="{Binding ActualWidth, ElementName=RightStackPanel}" Background="White" Content="Add" Height="50" Click="Button_Click" ></Button>
</Expander>
</StackPanel>
</ScrollViewer>
<Frame Grid.Column="0" x:Name="LeftFrame" Background="LightGray" ></Frame>
<Frame Grid.Column="1" x:Name="CenterFrame" Background="DarkGray" ></Frame>
</Grid></Window>
Other Xaml file
<Page
x:Name="Page"
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"
Title="Any" d:DesignWidth="1364" d:DesignHeight="868"
>
<Grid>
<Frame Background="DarkGray" />
</Grid></Page>
MainWindow.xaml.cs
private void Button_Click(object sender, RoutedEventArgs e)
{
Frame middleFrame=CenterColumn;
Otherxaml other=new Otherxaml();
middleFrame.Source = new Uri("OtherxamlPage.xaml", UriKind.RelativeOrAbsolute);
}
Pertinent to your code snippet, you may place the OtherxamlPage.xaml inside the central frame and set the properties of that frame like shown below:
<Frame Grid.Column="1" x:Name="CenterFrame" VerticalAlignment="Stretch" VerticalContentAlignment="Center" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" Source="OtherxamlPage.xaml" Background="DarkGray" />
You can set the Source="OtherxamlPage.xaml" dynamically in event handler, e.g. Button.Click as per your example.
Alternatively, consider the creation of WPF UserControl (re: https://msdn.microsoft.com/en-us/library/cc294992.aspx) instead of that other XAML Window (or Page) and place it directly into the grid cell. In both cases set the content "Stretch" property in order to adjust its size automatically, thus you won't need to specify it in the code.
Hope this may help.
Is it possible to set my StackPanel or Grid to be position absolute like CSS.
In CSS is have property Position of the elements and can set to be relative, absolute and is working good.
In XAML can make Grid, StackPanel to use position absolute.
You have to use Canvas in order to set absolute position in WPF.
In case of buttons in a window, here is a sample :
<Window x:Class="tobedeleted.MainWindow"
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"
Title="MainWindow" Height="350" Width="525">
<Canvas>
<Button Canvas.Left="10" Canvas.Bottom="20">Bottom left</Button>
</Canvas>
</Window>
The output is :
Feel free to ask if help is needed.
Absolute positioning defeats the purpose of WPF, but I agree, sometimes there is no other way so you have two basic options.
Elements under the root grid
Elements in a canvas that is the same size as the window (as Vasilievski pointed out)
Code example:
<Window x:Class="WpfApplication1.Window3"
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:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="Window3" Height="300" Width="300">
<Grid>
<Rectangle Fill="Red" Width="100" Height="120"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Panel.ZIndex="13"
Margin="12,34"
/>
<Rectangle Fill="Green" Width="100" Height="120"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="24,54"
/>
<Canvas>
<Rectangle Canvas.Left="5" Canvas.Top="5" Panel.ZIndex="2" Fill="Yellow" Width="120" Height="30" />
<Rectangle Canvas.Left="25" Canvas.Top="17" Panel.ZIndex="0" Fill="Blue" Width="120" Height="30" />
</Canvas>
</Grid>
</Window>
try this.
<StackPanel>
<Canvas>
<TextBlock Canvas.Left="10" Canvas.Top="6" Text="Choose a value from combobox:" Width="180"/>
<ComboBox Canvas.Left="190" Canvas.Top="4" Width="180"></ComboBox>
</Canvas>
</StackPanel>
RESULT:
I'm having trouble to adjust the Canvas inside the Grid in WPF. I want it to have a 10px margin from the Right and Top sides of the Grid. What am I doing wrong in the below code?
<Window x:Class="Layout2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid x:Name="DrawingArea" Background="Black">
<Canvas x:Name="InformationLayer"
Background="White"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Right="10"
Top="10"
Width="200" Height="30" >
</Canvas>
</Grid>
</Window>
Right and Top are attached properties of the Canvas class that position an element within a parent Canvas object. I do not believe they have a semantic meaning when used in the Canvas tag itself (unless of course you are nested in a canvas).
Instead, use the margin property:
<Canvas x:Name="InformationLayer"
Background="White"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Margin="0,10,10,0"
Width="200" Height="30" >
</Canvas>
Margins are formatted as "Left, Top, Right, Bottom" in case you need to modify!