How to find the child elements positions in a stack panel.
<StackPanel Orientation="Horizontal">
<ToggleButton Width="20"
Height="20"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Visibility="Visible" />
<TextBlock Margin="5"
VerticalAlignment="Center"
FontSize="15"
Text="Selection Mode" />
</StackPanel>
How to find the X,Y position of Toggle button and Text block?
You could always use TranslatePoint to translate coordinates relative to one UIElement to coordinates relative to another UIElement:
var toggleButtonPosition = toggleButton.TranslatePoint(new Point(0, 0), stackPanel);
var textBlockPosition = textBlock.TranslatePoint(new Point(0, 0), stackPanel);
The above code translates the point (0, 0) relative to the respective control to coordinates relative to the containing StackPanel, and hence gives the position of each control inside the StackPanel.
Basically, the position of a control is determined by the control which holds it, the margin property, the alignement and such.
You could use this to determine the position of the child control.
Related
I'm attempting to align a flow document to the left with no padding, so that it matches exactly what you see in a TextBlock. I've recreated a simple example of what I'm basically trying to achieve. Here's what I have so far:
<Grid>
<TextBlock Foreground="Red" Height="Auto" TextWrapping="Wrap"
Margin="0" Padding="0" FontSize="50" FontFamily="Arial"
Text="Some text."/>
<RichTextBox BorderThickness="0" Background="Transparent" BorderBrush="Transparent" IsInactiveSelectionHighlightEnabled="False" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Disabled"
Height="Auto"
Margin="0" Padding="0" FontSize="50" FontFamily="Arial" >
<FlowDocument PagePadding="0" LineStackingStrategy="BlockLineHeight">
<Paragraph Margin="0" Padding="0" TextIndent="0">Some text.</Paragraph>
</FlowDocument>
</RichTextBox>
</Grid>
Here's the result:
As you can see, the red is the TextBlock version and the black is the RichTextBox/FlowDocument version. The FlowDocument text is offset by about 5 pixels to the right. I've tried to remove all padding that I am aware of, but I still can't get rid of that offset. Any help is appreciated.
NOTE: This question is found as duplicate of WPF: How to make RichTextBox look like TextBlock?
This offset is related to the caret implementation in the RichTextBox control.
Look at .Net 4.8 source, in the RichTextBox.cs file:
// Allocates the initial render scope for this control.
internal override FrameworkElement CreateRenderScope()
{
FlowDocumentView renderScope = new FlowDocumentView();
renderScope.Document = this.Document;
// Set a margin so that the BiDi Or Italic caret has room to render at the edges of content.
// Otherwise, anti-aliasing or italic causes the caret to be partially clipped.
renderScope.Document.PagePadding = new Thickness(CaretElement.CaretPaddingWidth, 0, CaretElement.CaretPaddingWidth, 0);
// We want current style to ignore all properties from theme style for renderScope.
renderScope.OverridesDefaultStyle = true;
return renderScope;
}
And the CaretElement.CaretPaddingWidth definition in the CaretElement.cs file:
// Caret padding width to ensure the visible caret for Bidi and Italic.
// Control(TextBox/RichTextBox) must have the enough padding to display
// BiDi and Italic caret indicator.
internal const double CaretPaddingWidth = 5.0;
Therefore, the only option that you can check is set the RichTextBox margin to Margin="-5,0,0,0".
I am using UWP and working with the Composition API to programmatically scale child text visuals that are nested in a typical XAML hierarchy. The textblocks in our app are contained in things like borders and a number of those borders are items contained in a GridView.
In many of the scenarios I am experiencing clipping of the associated text visual as it scales to be larger than some of the XAML containers that host the elements and I would like the visual to not get clipped as it scales to be larger than its parent.
Here is a barebone example that demonstrates some of the problems I am seeing…
My test app starts as a blank UWP app and the root grid of my page contains the following Gridview:
<GridView >
<GridViewItem>
<Border PointerPressed="Border_PointerPressed" CornerRadius="5" Width="125" Height="125">
<Grid>
<TextBlock Text="Content String 1" />
</Grid>
</Border>
</GridViewItem>
<GridViewItem>
<Border PointerPressed="Border_PointerPressed" Width="125" Height="125">
<Grid>
<TextBlock Text="Content String 2" />
</Grid>
</Border>
</GridViewItem>
<GridViewItem>
<Border PointerPressed="Border_PointerPressed" Width="125" Height="125">
<Grid>
<TextBlock Text="Content String 3"/>
</Grid>
</Border>
</GridViewItem>
</GridView>
The codebehind file contains the following additional using statements, a variable declaration, variable initialization in page constructor and this event handler:
using System.Numerics;
using Windows.UI.Composition;
using Windows.UI.Xaml.Hosting;
Compositor compositor;
public MainPage()
{
this.InitializeComponent();
compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
}
private void Border_PointerPressed(object sender, PointerRoutedEventArgs e)
{
var content = VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(sender as FrameworkElement, 0), 0);
var visual = ElementCompositionPreview.GetElementVisual(content as FrameworkElement);
var animation = compositor.CreateVector3KeyFrameAnimation();
animation.InsertKeyFrame(0f, new Vector3(1.0f, 1.0f, 0.0f));
animation.InsertKeyFrame(0.5f, new Vector3(3.0f, 3.0f, 0.0f));
animation.InsertKeyFrame(1f, new Vector3(1.0f, 1.0f, 0.0f));
animation.Duration = TimeSpan.FromMilliseconds(5000);
visual.StartAnimation(nameof(visual.Scale), animation);
}
When you run the app and click on each of the strings you should initially notice that the first string behaves differently than the other two string.
The first string gets cropped at the Border's bounding box whereas the other two strings do not.
Also note that the other two strings appear to scale past the bounds of last item and out into the page, but that turns out to probably be due to the gridview autosizing to fill the page.
The difference between the first string and the other two is that the border has a corner radius property set on it. We use cornerradius setting in our application, so it would be nice to know if there is a way to override or control this behavior so that it doesn't clip the visual as it scales.
The other behavior that is causing us problems is that at the GridView bounds is another boundary that the visual is clipping at as it scales. If you set any property (like HorizontalAlignment="Center") on the Gridview that causes it to size itself to only be as big as it needs to be, then the visual gets cropped at the controls boundaries.
Is there anything within the Compositional API that allows me to prevent or influence this clipping behavior?
I want to know if there is a way to resize the frame and the elements inside of it when the window size change. I always want to have the same proportion in the size of the elements inside the frame.
Example:
1- Windowsize = 100(in x) and Imagesize = 50(in x) locationx = 25
2- Windowsize = 50(in x) and Imagesize = 25(in x) location x = 12.5(~12)
In this case, the windowsize is "something", imagesize is 1/2 of "something" and locationx of the image is 1/4 of something. I wan't to do something like this but with every element inside the frame.
Thanks!
You can use the <ViewBox/> control which does exactly that.
<Page>...
<Grid>
<ViewBox HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<StackPanel>
<Button Content="test" HorizontalAlignment="Left"/>
<TextBlock Text="some text"/>
</StackPanel>
</ViewBox>
</Grid>
</Page>
In the example below, the ViewBox is placed inside a Grid and stretched both Horizontally and Vertically which causes it to stretch with the Page resize.
Reference docs here.
I have seen several similar questions to this, but no solution works for me, probably because my Grid is set to Stretch . This is the result I am trying to achieve. Basically, I have one Grid and I'd like to draw an X-Axis line( like in the picture at the end of this question).
My XAML
<Grid x:Name="MainGrid" HorizontalAlignment="Stretch" Background="#FF4A70F1">
My CodeBehind
Line XAxis = new Line();
XAxis.Stroke = System.Windows.Media.Brushes.Black;
XAxis.StrokeThickness = 1;
XAxis.X1 = 0;
XAxis.X2 = MainGrid.RenderSize.Width;
XAxis.Y1 = MainGrid.RenderSize.Height / 2;
XAxis.Y2 = MainGrid.RenderSize.Height / 2;
MainGrid.Children.Add(XAxis);
My Problem
I 'd like this line to span the whole window, even if I resize/maximize the window. However, the calculations above for X2,Y1,Y2 don't work( all evaluate to 0, hence NO LINE shown) , whether I use ActualSizeor *RenderSize* . Can someone please point out how to fix that? Thank you
This XAML creates a vertically centered line that stretches horizontally:
<Grid>
<Line HorizontalAlignment="Left" VerticalAlignment="Center" Stroke="Black"
X2="{Binding ActualWidth,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Grid}}"/>
</Grid>
I'm trying to create a function that moves images arranged in a radial layout around in a circle by swapping each one's position with their neighbor's position. The final effect is that the images are rotating around in a circle. The transform is activated when the S (counterclockwise) or D (clockwise) keys are pressed. I'm using an array to track the positions of the images and sending those coordinates to a function that actually does the transform.
The first rotation in either direction works fine. But any consecutive rotation in the same direction produces strange unwanted movement. In essence, with every new rotation the images all move inward towards the center of the circle before moving out again to take their final positions. The amount of inward motion gets worse with each key press.
Since I'm not allowed to attach an image to this email I have posted one here:
http://i1266.photobucket.com/albums/jj532/ik_al/screencap.jpg
The image shows a series of screenshots to illustrate the phenomenon. Please note that the screenshots are all happening on ONE rotation.
Here's my XAML file:
<Window x:Class="radialLayout.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:MyNamespace="clr-namespace:radialLayout"
Title="MainWindow" Height="350" Width="525" KeyUp="Window_KeyUp">
<Grid Width="1024" Height="768">
<MyNamespace:RadialPanel Margin="27,21,31,32" MouseWheel="RadialPanel_MouseWheel" x:Name="ImagePanel">
<!--Must use same namespace declared above-->
<!--Each image must have a unique name-->
<Image Height="49" Name="image1" Width="74" Source="/radialLayout;component/Images/profile.jpg" />
<Image Height="49" Name="image2" Width="74" Source="/radialLayout;component/Images/IMG_0841.JPG" />
<Image Height="49" Name="image3" Width="74" Source="/radialLayout;component/Images/profile.jpg" />
<Image Height="49" Name="image4" Width="74" Source="/radialLayout;component/Images/IMG_0841.JPG" />
<Image Height="49" Name="image5" Width="74" Source="/radialLayout;component/Images/profile.jpg" />
<Image Height="49" Name="image6" Width="74" Source="/radialLayout;component/Images/IMG_0863.JPG" />
<Image Height="49" Name="image7" Width="74" Source="/radialLayout;component/Images/profile.jpg" />
<Image Height="49" Name="image8" Width="74" Source="/radialLayout;component/Images/IMG_1043.JPG" />
<Image Height="49" Name="image9" Width="74" Source="/radialLayout;component/Images/profile.jpg" />
<Image Height="49" Name="image10" Width="74" Source="/radialLayout;component/Images/IMG_0863.JPG" />
<Image Height="49" Name="image11" Width="74" Source="/radialLayout;component/Images/profile.jpg" />
<Image Height="49" Name="image12" Width="74" Source="/radialLayout;component/Images/IMG_0863.JPG" />
</MyNamespace:RadialPanel>
And here is the function call and function implementation:
for (int o = 0; o < VisualTreeHelper.GetChildrenCount(ImagePanel); o++)
{
Visual childVisual = (Visual)VisualTreeHelper.GetChild(ImagePanel, o);
MyExtensions.MoveTo((Image)childVisual, lastPosition[o, 0], lastPosition[o, 1], ImagePanel.imageCoordinates[o, 0], ImagePanel.imageCoordinates[o, 1]);
}
public static void MoveTo(this Image target, double currentX, double currentY, double newX, double newY)
{
Vector offset = VisualTreeHelper.GetOffset(target);
var top = offset.Y;
var left = offset.X;
TranslateTransform trans = new TranslateTransform();
target.RenderTransform = trans;
DoubleAnimation anim1 = new DoubleAnimation(0, newY - top, TimeSpan.FromSeconds(1));
DoubleAnimation anim2 = new DoubleAnimation(0, newX - left, TimeSpan.FromSeconds(1));
trans.BeginAnimation(TranslateTransform.YProperty, anim1);
trans.BeginAnimation(TranslateTransform.XProperty, anim2);
}
Does anyone know what is causing this behavior or how to fix it?
After much investigation I finally figured out what I was doing wrong in my code.
I didn't understand that when using translateTranform the original position of the images is retained as the starting point for all consecutive transforms; I assumed it was updated to the last most current position. In addition, this starting point is always referenced by coordinates (0,0).
So to fix my animation problem I had to offset the start and stop positions of my images by subtracting each image's original position (before the first transform) from the current placement of the image on the screen (as stored in the array). For the first pass through these values will always add up to 0.
I was already completing this offset for the stop positions since it was necessary to get even the first transform to work. But as it turned out, this subtraction was needed to update the start positions as well.
In the code the original position of the image is stored in the left and top variables which reference the X and Y coordinates respectively.
Here's the part of the code that I changed:
DoubleAnimation anim1 = new DoubleAnimation(currentY-top, newY - top, TimeSpan.FromSeconds(1));
DoubleAnimation anim2 = new DoubleAnimation(currentX-left, newX - left, TimeSpan.FromSeconds(1));
What was interesting about this error was that the resulting animation when all 12 images were transformed together was much more complex and interesting than it would have been if each image was moved individually. So there must be some interaction between how the image transforms are computed that produces emergent output. The output I was seeing made me think the solution was much more complex than it actually was.