How to get RelativePanel's Canvas.Top value in C# code? - c#

I have code as below. Which puts a RelativePanel inside of a Canvas. And I apply animation onto the panel, which will move it down 230 pixels, i.e. to change its Canvas.Top="0" to Canvas.Top="230"
In the C# code, I need to detect whether the animation works. So I need to get the Canvas.Top of the RelativePanel.
But how?
Thanks!
<Canvas x:Name="toolbarCanvas" Margin="0,0,0,-50" Height="140" Width="1000" RelativePanel.AlignBottomWithPanel="True" RelativePanel.AlignHorizontalCenterWithPanel="True">
<RelativePanel x:Name="toolbarPanel" Margin="0,0,0,0" Canvas.Top="230">
<Image x:Name="toolbarBackground" Source="Assets/MainPage/toolbar/toolbar-background.png" Height="140" Width="1000" Stretch="Uniform" RelativePanel.AlignHorizontalCenterWithPanel="True" />
</RelativePanel>
</Canvas>

Since Canvas.Top is an attached property you can simply use:
var top = Canvas.GetTop(toolbarPanel);

Related

How to Fill SolidColorBrush/Ellipse [duplicate]

I am trying to create this in WPF (I realize I could just use an image, but I am trying to learn WPF):
(source)
This is what I have so far but it isn't producing the desired result, in that, the textbox seems completely hide the ellipse whereas it should simply have a transparent background:
<StackPanel>
<TextBlock HorizontalAlignment="Left" Margin="144,207,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top"/>
<Ellipse HorizontalAlignment="Left" Height="52" Margin="142,189,0,0" Stroke="Black" VerticalAlignment="Top" Width="52"/>
</StackPanel>
You can put things like this in a viewbox to make scaling easier, something like this. You'll need to remove the stack panel, it's going to stack items one on top of the other which isn't what you're after here. I used a grid in this case.
<Viewbox Width="100" Height="100">
<Grid Width="20" Height="20">
<Ellipse Stroke="Black"/>
<TextBlock HorizontalAlignment="Center" Text="i" TextAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Viewbox>
Or you can use the unicode character: ⓘ
code 0x24D8
<TextBlock Text="ⓘ" FontSize="52" />
So a stackpanel will place the first item at the top, the second just below it, third below the second, and so forth. What you could do is use a Canvas or a Grid. Like the stackpanel, they are "Content Controls" and support placing multiple objects inside of them like you have done with the stackpanel.
So a really quick way to do what you're trying to accomplish would be:
<Grid >
<Ellipse HorizontalAlignment="Left" Height="52" Stroke="Black" VerticalAlignment="Top" Width="52"/>
<TextBlock Text="i" FontSize="52" Margin="18,-13,-6,13" />
</Grid>
You can do it using a border and a TextBlock. A square border will become a circle if you make its CornerRadius equals half its Width (or Height):
<Border Width="100" Height="100" CornerRadius="50" BorderBrush="Black" BorderThickness="2">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"
FontSize="50" Foreground="Blue" >i</TextBlock>
</Border>
Don't use a StackPanel for this, the purpose of it is to stack things, not show them overlapped, you're using the wrong tool for that. Use a Grid, it's far more suited for what you're trying to do.
To have a transparent background, you have to either set the TextBlock's Background property to Transparent, or set a null background.
Background={x:Null}

Blur images no matter what in WPF

I have a button with an image and no matter what I do the image looks blurry after rendered/compiled.
FYI - The image looks good when not in WPF controls
The image on the left is before compiled, the image on the right is blurry after compiled.
I tried applying UseLayoutRounding, applying SnapsToDevicePixels,
RenderOptions.BitmapScalingMode and removing the antialiasing directly in the button and directly to the image but nothing.
Any idea how can I improve the quality of the images in WPF?
XAML:
Styles applied directly to the button:
<Grid>
<Button x:Name="recentButton" UseLayoutRounding="True" RenderOptions.BitmapScalingMode="HighQuality" SnapsToDevicePixels="True" RenderOptions.EdgeMode="Aliased"
Margin="10,137,302,10"
Width="auto"
Height="23"
HorizontalAlignment="Stretch"
BorderBrush="{x:Null}"
Foreground="White"
BorderThickness="0"
Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">
<Image Source="/Tool;component/Design/Images/more-icon-active.png" Stretch="None"/>
</Button>
</Grid>
Styles applied directly to the image:
<Grid>
<Button x:Name="recentButton"
Margin="10,137,302,10"
Width="auto"
Height="23"
HorizontalAlignment="Stretch"
BorderBrush="{x:Null}"
Foreground="White"
BorderThickness="0"
Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">
<Image Source="/Tool;component/Design/Images/more-icon-active.png" UseLayoutRounding="True" RenderOptions.BitmapScalingMode="HighQuality" SnapsToDevicePixels="True" RenderOptions.EdgeMode="Aliased" Stretch="None"/>
</Button>
</Grid>
The problem is you're using UseLayoutRounding on the control directly.
But, be aware of this note in the linked documentation,
You should set UseLayoutRounding to true on the root element. The layout system adds child coordinates to the parent coordinates; therefore, if the parent coordinates are not on a pixel boundary, the child coordinates are also not on a pixel boundary. If UseLayoutRounding cannot be set at the root, set SnapsToDevicePixels on the child to obtain the effect that you want.
Therefore, use it on the parent container instead. In your case, that would be on the on the <grid> element.
Other recommandations
Recommended by #Clemens in the comment section,
Depending on the kind of image, RenderOptions.BitmapScalingMode="NearestNeighbor" may add some sharpness.
Note that you will have to apply that on the image directly.
Recommended by #BradleyUffner in the comment section,
Setting TextOptions.TextFormattingMode="Display" on your top level elements to greatly improve text rendering on desktop computers.

scrollviewer zoom only one element

I have to zoom an image in uwp application, which works fine, but the design requires to have another image (that works as a button) in front of it and I dont want that element to be zoomed as well. It has to be only the image inside the canvas tag, this is how I have it now.
<ScrollViewer MinZoomFactor="1"
ZoomMode="Enabled"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto">
<RelativePanel HorizontalAlignment = "Stretch" >
<Canvas x:Name="canvas">
<Image Source = "{Binding Test,UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
</Canvas >
<Button RelativePanel.AlignTopWithPanel="True"
Height="55"
Command="{Binding Path=CollapseSplitView}"
CommandParameter="{Binding ElementName=SplitV}">
<Button.Background>
<ImageBrush ImageSource = "/Assets/btlist.png" ></ ImageBrush >
</Button.Background >
</Button >
<Image RelativePanel.AlignBottomWithPanel="True"
RelativePanel.AlignRightWithPanel="True"
Source="/Assets/escala-x.png"
Width="130"
Height="70"
Margin="0,0,20,0"
ScrollViewer.IsZoomChainingEnabled="False"
ScrollViewer.IsZoomInertiaEnabled="False">
</Image>
</RelativePanel>
</ScrollViewer>
thats the xaml I have and which makes the zoom work for all elements inside of it. I tried to set scrollViewer.zoomMode=disabled for the elements that are not in the canvas but without luck. Any ideas? Thanks!
I finally fixed it by adding a scrollViewer inside the RelativePanel and then wrap the contents I wanted to zoom inside a StackPanel and then a Grid to be able to have multiple elements inside. Thanks all

Set position of Image programatically in Windows Store App

I am developing a Windows Store application with C# and XAML in which I have an image being displayed on user screen. On certain event I want to change its position on screen to the coordinates of my choice.
I have tried
Canvas.SetLeft(selectedImage, screenCoords.X);
Canvas.SetTop(selectedImage, screenCoords.Y);
and
selectedImage.SetValue(Canvas.LeftProperty, screenCoords.X);
selectedImage.SetValue(Canvas.TopProperty, screenCoords.Y);
But they are not working. I have also tried updating the layout after this. can anyone tell me what exactly am I doing wrong here?
Here is the XAML code:
<FlipView.ItemTemplate>
<DataTemplate>
<Grid x:Name="cv">
<Image x:Name="img1" Source = "{Binding ModelImage}" Stretch="Fill" Tag="{Binding ModelTag}" Tapped="ModelTapped"/>
<Image x:Name="hat" Source = "{Binding HatImage}" Width="{Binding HatWidth, Mode=TwoWay}" Height="{Binding HatHeight, Mode=TwoWay}" Stretch="Fill" ManipulationMode="All" ManipulationDelta="ResourceImage_ManipulationDelta" Tapped="imageTapped" Tag="{Binding hatTag}" Canvas.ZIndex="3">
<Image.RenderTransform>
<CompositeTransform />
</Image.RenderTransform>
</Image>
</Grid>
</DataTemplate>
</FlipView.ItemTemplate>
I have several images in the grid named 'cv', just removed them for simplicity. selectedImage in above C# code is one of the images in the grid 'cv'.
I solved the issue by translating my image to the desired points using RenderTransform property.

How to place a slider over on top of a videobrush

I am attempting to create a slider control which will determine the scaletransform of a videobrush in my MainPage, and was wondering if it was possible to somehow place this slider on top of the videobrush (which I would like to be full screen)? Currently I am using a grid for my layout where a videobrush takes up the whole screen except for two buttons on the bottom of the screen, but I would like to possibly use a canvas and place this slider in a way that would account for the current and future screen sizes of a Windows Phone device. I am unsure of how to exactly accomplish this without setting constant dimensions for the slider. For instance the slider may be placed horizontally near the bottom of the screen in Portrait mode and would have a 50 pixel space between the left and right sides. Could someone assist with how this could be done?
EDIT
Placing a single child element over the videobrush works, although I would like to place more than one slider which gives an error. I also wanted to add information above and below each slider so I chose a stackpanel to do this (yet only one stackpanel as a child element is allowed?).
<Border x:Name="videoRectangle" Grid.Row="0" Grid.ColumnSpan="2" >
<Border.Background>
<VideoBrush x:Name="viewfinderBrush">
<VideoBrush.RelativeTransform>
<CompositeTransform x:Name="viewfinderBrushTransform" CenterX=".5" CenterY=".5" Rotation="90" />
</VideoBrush.RelativeTransform>
</VideoBrush>
</Border.Background>
<!--<StackPanel VerticalAlignment="Top">
<TextBlock x:Name="resolutionValueTextBlock" HorizontalAlignment="Center" Text="{Binding Value, ElementName=resolutionSlider}"/>
<Slider x:Name="resolutionSlider" HorizontalAlignment="Stretch" Margin="50,5,50,5"/>
<TextBlock x:Name="resolutionTextBlock" HorizontalAlignment="Center" Text="resolution"/>
</StackPanel>-->
<StackPanel VerticalAlignment="Bottom">
<TextBlock x:Name="zoomNumberTextBlock" HorizontalAlignment="Center" Text="{Binding Value, ElementName=zoomSlider}"/>
<Slider x:Name="zoomSlider" HorizontalAlignment="Stretch" Margin="50,5,50,5"/>
<TextBlock x:Name="zoomTextBlock" HorizontalAlignment="Center" Text="zoom"/>
</StackPanel>
</Border>
If possible I would like both stackpanels to be available, but if not I guess I would have to use the bottom one only.
Stay with the Grid:
<Grid>
<Rectangle>
<Rectangle.Fill>
<VideoBrush ... />
</Rectangle.Fill>
</Rectangle>
<Slider HorizontalAlignment="Stretch"
VerticalAlignment="Bottom"
Margin="50,5,50,5"/>
</Grid>

Categories