WPF ViewBox Zoom - c#

Is there a way to zoom a viewbox content, excpet for one control?
I have a viewbox with a grid, and in this grid I have some controls and I'm trying to zoom all the controls in the viewbox except one, is it possible?
Many thanks,
Paulo

You can use a grid to add layers to your layout. That way, you can zoom one set of items, and leave another set un-zoomed.
<Grid>
<Viewbox>
<!-- Controls to zoom -->
</Viewbox>
<!-- Control to exclude from zoom -->
</Grid>
The order of the view box and the other controls in XAML will depend upon which layer appears on top.
If that doesn't quite do what you want, leave a comment and I'll revisit the answer.
EDIT You want the unzoomed control to be positioned relative to the (0,0) of the Viewbox. That will happen in this situation because both children of the grid are in cell (0,0) which means that their top-left corners are aligned. Can you give an example of what you have in XAML, and what's wrong with it (perhaps edit your original question)?
Here's some XAML to try:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Background="Green">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Viewbox>
<Rectangle Fill="Yellow" Width="10" Height="10" />
</Viewbox>
<TextBlock>I am positioned at (0,0)</TextBlock>
<TextBlock Margin="50,50">I am positioned at (50,50)</TextBlock>
</Grid>
</Page>
That gives a layout like this:
http://img20.imageshack.us/img20/2045/layout1m.png
But note that when the height is reduced, the grid becomes wider than the view box, and so the content is layed out like this:
http://img20.imageshack.us/img20/9397/layout2i.png
I guess that's not what you want. In that case, you use a canvas and go for something like this:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Background="Green">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Viewbox>
<Rectangle Fill="Yellow" Width="10" Height="10" />
</Viewbox>
<Canvas>
<TextBlock>I am positioned at (0,0)</TextBlock>
<TextBlock Margin="50,50">I am positioned at (50,50)</TextBlock>
</Canvas>
</Grid>
</Page>
Which looks like this:
http://img20.imageshack.us/img20/6743/layout3i.png

Related

Is there a way to swap a StackPanel orientation from "Horizontal" to "Vertical" based on container width?

I have two fixed-size elements currently in a Grid, laid out horizontally. A user has requested to be able to stretch the container vertically and shrink it horizontally, in order to have those two elements appear stacked vertically. I've swapped from a Grid to a StackPanel, but my final hurdle is having the Orientation change. The basic logic would be:
<StackPanel HorizontalAlignment="Center" Orientation="{Binding (ActualWidth < ActualHeight ? "Vertical" : "Horizontal")}">
I apologise if this question is overly vague, I'm still getting used to WPF! Please let me know if there are any additional details that are required to answer this question.
A WrapPanel should give you the behavior that you want. Here is a simple example:
<Grid>
<WrapPanel HorizontalAlignment="Center">
<Rectangle
Width="200"
Height="200"
Fill="Red" />
<Rectangle
Width="200"
Height="200"
Fill="Blue" />
</WrapPanel>
</Grid>

UWP Fit zoomable image in its container

To make an image zoomable I'm using wrapping the image control with a ScrollViewer like such:
<Page ...>
<ScrollViewer ZoomMode="Enabled" HorizontalScrollMode="Auto" VerticalScrollMode="Auto">
<Image Source="http://i.imgur.com/iseJWq1.jpg" />
</ScrollViewer>
</Page>
I want the image to be resized to fit inside the page in both horizontal and vertical directions, just like the Stretch="Uniform" behaviour of the Image control:
But instead it resizes the image to fit horizontally only, clipping the excess of the image on the vertical direction:
I got some head start from this website, so I changed the xaml to look like:
<Page x:Name="Page"
... />
<ScrollViewer ZoomMode="Enabled" HorizontalScrollMode="Auto" VerticalScrollMode="Auto">
<Image Source="http://i.imgur.com/iseJWq1.jpg" Width="{Binding ActualWidth, ElementName=Page}" Height="{Binding ActualHeight, ElementName=Page}" />
</ScrollViewer>
</Page>
While this works fine on the stretching side of things, the image then becomes aligned to the left of the screen, and weird things happen when you zoom in/out:
Playing with the Stretch properties of the image have no effect.
How do I then make the image zoomable while initially fitting the image inside its container, just like any photo viewer app would do?
This works:
<Page x:Name="Page" ...>
<ScrollViewer ZoomMode="Enabled" MinZoomFactor="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Image Source="http://i.imgur.com/iseJWq1.jpg" MaxWidth="{Binding ActualWidth, ElementName=Page}" MaxHeight="{Binding ActualHeight, ElementName=Page}"/>
</ScrollViewer>
</Page>
...which is exactly what the article recommended to be done.

how to avoid a single pixel line disappear in wpf?

I use a Path element(StrokeThickness="1" SnapsToDevicePixels="True")
in Grid. I want to resize the window, the Grid element is wrapped by a Viewbox element.
Problem
When I resize the window, the Path will disappear some time. If I turn SnapsToDevicePixels to false, the Path element may blur which is not what I want.
How to avoid a single pixel line dispear?
the XAML code:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="207" Width="475">
<Viewbox Stretch="Fill">
<Grid Height="320" Width="517">
<Path Data="M0,0 H1 z" StrokeThickness="1" Stroke="Black" Margin="72,73,79,218" Stretch="Fill" SnapsToDevicePixels="True" MinHeight="1"/>
</Grid>
</Viewbox>
Pity for I have no reputation to post the runtime effect.
I have experimented the same problem with separators put in a Viewbox. Some of these disappear for some resolutions. To fix it, I replace them with border with 1 pixel height :
< Border Background="DarkGray" Grid.Row="0" Grid.ColumnSpan="7" Height="1" />
This avoid single line of one pixel to disappear in viewBox.
Hope it could be useful for you too.

Resizing inkcanvas to the left and top

I want to resize width and height of inkcanvas to fit the screen. When I resized it, the width expands to the right and height expands to the bottom. But inkcanvas is not fit to screen.
I also want to fix the position of inkcanvas child element. If I can resize inkcanvas to fit the screen, the position of inkcanvas child element will not change.
How do I resize inkcanvas to the left and top to fit the screen?
<Canvas x:Name="Screen" >
<InkCanvas Name="inkcanvas" ResizeEnabled="True"
Width="{Binding ElementName=LayoutRoot, Path=ActualWidth}"
Height="{Binding ElementName=LayoutRoot, Path=ActualHeight}"
EditingMode="Select" ClipToBounds="False"
Background="Bisque"
SelectionChanging="OnSelectionChanging"
Visibility="Collapsed" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<!-- InkCanvas' Child Elements -->
</InkCanvas>
<Canvas.RenderTransform>
<MatrixTransform/>
</Canvas.RenderTransform>
</Canvas>
Thanks
Update:
I put inkcanvas in a grid. It fit to the screen but the position of child element is changed.
I want to fix the red rectangle position.
The position of red rectangle should not be changed.
<Grid>
<InkCanvas x:Name="inkcanvas" Background="Transparent">
<Rectangle Height="41" HorizontalAlignment="Left" Name="rectangle1" Stroke="Black" VerticalAlignment="Top" Width="69" Fill="#FFDB1111" />
</InkCanvas>
</Grid>
My big picure:
My WPF Application contain many pictures. I can zoom in/out the canvas. I can select the pictures by using selection tool.
I have canvas and inkcanvas.
canvas: contain picture and zoom in/out
inkcanvas: has selection tool
If I zoom out, the canvas and inkcanvas become smaller.
If I use selection tool, I copy all pictures from canvas to inkcanvas.
But the inkcanvas is zoom out, I cannot use selection tool if outside the inkcanvas boundary.
It is the reason why I want to resize inkcanvas and fix the children position.
<Window x:Class="WpfInkCavasSaveImage.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="1091" Width="873" WindowState="Maximized">
<Grid Margin="0,0,0,10" >
<Grid.RowDefinitions>
<RowDefinition Height="1200*" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<InkCanvas HorizontalAlignment="Stretch" Margin="1,1,1,10" x:Name="inkCanvas1" VerticalAlignment="Stretch" Width="Auto" RenderTransformOrigin="0.5,0.5" Background="LightGreen" SnapsToDevicePixels="True" IsManipulationEnabled ="True" Grid.RowSpan="2">
<InkCanvas.CacheMode>
<BitmapCache/>
</InkCanvas.CacheMode>
<InkCanvas.DefaultDrawingAttributes>
<DrawingAttributes Color="Black" FitToCurve="True" Height="2.0031496062992127" IgnorePressure="False" IsHighlighter="False" StylusTip="Ellipse" StylusTipTransform="Identity" Width="2.0031496062992127"/>
</InkCanvas.DefaultDrawingAttributes>
</InkCanvas>
</Grid>
</Window>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
inkCanvas1.Width = System.Windows.SystemParameters.WorkArea.Width;
inkCanvas1.Height = System.Windows.SystemParameters.WorkArea.Height;
}
}
This depends on the container around the InkCanvas. Further you cannot expect the child-elements not to move if you mess with their container. If you need the child elements to behave independently of the InkCanvas you might want to rethink if that is a good idea and if what you want to accomplish can not be done more efficiently using another setup.
You should tell us more about what the big picture is of what you want to achieve, the fact that children are affected by manipulations of their container is expected and generally wanted. Maybe there is a better approach than to try and scale the container and at the same time having to shift all children around to nullify such a manipulation.
Remove all the margins from the inkcanvas and put it in a Grid.
Could you explain why this would not work for you?
<Grid>
<InkCanvas>
...
</InkCanvas>
</Grid>
Edit There are two way to keep the child element where it is:
As soon as the position or the size of the InkCanvas changes adjust the child positions accordingly. this means that you have to pick a fixed position (window topleft, screen topleft, ...) that determines the actual position of the child.
Remove the child from the InkCanvas and put it in the correct container (the one that determines the child's position.
I would prefer #2 as is is more logical and requires less calculations/event-handling

C# WPF - ScrollViewer + TextBlock troubles

I have a TextBlock within a ScrollViewer that aligns with stretch to its window. I need the TextBlock to behave as the following:
Resizes with window, no scrollbars
When resized below a certain width the TextBlock needs to keep a MinWidth and scrollbars should appear
TextWrapping or TextTrimming should work appropriately
How can I get this functionality?
I have tried several ways, involving bindings to ActualWidth & ActualHeight, but can't get it to work.
This can't be that difficult, what am I missing?
Here is a code sample to put in XamlPad (no MinWidth is set yet):
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<TextBlock TextWrapping="Wrap" Text="Some really long text that should probably wordwrap when you resize the window." />
</ScrollViewer>
</Window>
This works:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ScrollViewer HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto"
Name="Scroller">
<TextBlock HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
MinWidth="100"
Width="{Binding ElementName=Scroller, Path=ViewportWidth}"
TextWrapping="Wrap"
Text="Some really long text that should probably wordwrap when you resize the window." />
</ScrollViewer>
</Window>
Without more detail, the best I can do is provide the standard way of doing this. Basically, host your element (which has a minimum size) in a scroll viewer; when the scrollviewer is resized small enough such that the element cannot wholly fit inside it, it will automatically display scroll bars. Example:
<ScrollViewer>
<Button MinWidth="100" MinHeight="50"/>
</ScrollViewer>

Categories

Resources