I am developing a control (Items control) to show boxes in a Room(for example sack).
If the room size is 10 *10 feet then I have to scale it to fit my Screen.
Also all the objects in the room will also need to be scaled.
In my view model I have a collection of these objects(i.e. boxes) with actual dimension.
The ItemPanel of my items control is like a canvas where I can freely move the objects.
currently in my Measure Override or Arrange override of the itemsPanel I get the height and width of the panel. With that height and width I apply the scaling to object while arranging.
So my question is, is the approach better or there is a better alternative.
Regards
Saurabh Dighade
Take a look at this code
<Grid x:Uid="Grid_1" Margin="10" ToolTip="{Binding ToolTip}">
<StackPanel x:Uid="StackPanel_1" Grid.Row="1" Orientation="Horizontal">
<Slider x:Uid="ScaleSlider" x:Name="ScaleSlider" Minimum="0.2" Maximum="5" LargeChange="0.05" SmallChange="0.01"
Value="{Binding ScaleSlider}" IsSnapToTickEnabled="True" TickFrequency="0.1" Visibility="Hidden"/>
</StackPanel>
<ScrollViewer x:Uid="ScrollViewer_1" Grid.Row="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Border x:Uid="AlStatusBorder" BorderBrush="#101010" BorderThickness="3"
Background="{Binding Color}"
x:Name="AlStatusBorder"
Padding="5"
CornerRadius="10" HorizontalAlignment="Center" VerticalAlignment="Top">
<Grid x:Uid="Grid_2">
<!-- Tachometer Gauge -->
<gauge:CircularGauge x:Uid="gauge:CircularGauge_1" Grid.Row="1" Grid.Column="2" FrameType="CircularTopGradient" Width="150" Height="150" Radius="75" Background="#444444"
RimBrush="#444444">
<gauge:CircularGauge.LayoutTransform >
<ScaleTransform x:Uid="ScaleTransform_1" ScaleX="{Binding ElementName=ScaleSlider, Path=Value}"
ScaleY="{Binding ElementName=ScaleSlider, Path=Value}"/>
</gauge:CircularGauge.LayoutTransform>
</gauge:CircularGauge>
</Grid>
</Border>
</ScrollViewer>
</Grid>
In grid_2 I implement my userControl. When I change a property ScaleSlider, element becomes bigger or smaller, and my usercontrol that is inside also changes it's sizes. May be it is what you are looking for. At least I can move this userControl; change sizes only by changing one property. Note that Im binding ScaleX and ScaleY values
Related
I have a custom WPF control based on Soroosh Davaee’s ImageButton example at http://www.codeproject.com/Tips/773386/WPF-ImageButton. The custom control combines an Image and TextBlock in a horizontal StackPanel within a Button. (BTW, to get Soroosh’s example to run, I had to edit the solution properties so that “SampleView” is the startup project rather than “ExtendedButton” being the startup project.)
I want the text in the TextBlock to automatically shrink if necessary to avoid clipping at the right edge if the text is too long to fit naturally in the button. For example, if I edit Soroosh's MainWindow.xaml to make the button text too long to fit...
...
<EB:ImageButton Width="100" Height="30" Content="TextTooLongToFitInTheButton" Grid.Row="2"
...
<EB:ImageButton Width="100" Height="30" Content="TextTooLongToFitInTheButton" Grid.Row="2"
...
...the result is the following buttons with clipped text:
In researching this, it seems the simplest way to auto-shrink the content of a TextBlock is to wrap it within a Viewbox:
<Viewbox StretchDirection="DownOnly" Stretch="Fill">
<TextBlock ... />
</Viewbox>
DownOnly apparently prevents the Viewbox from enlarging the text to fill the space, and Fill (as opposed to Uniform) seems to tell it to stretch (shrink) only the dimension that needs to shrink (i.e. the horizontal dimension in my case).
In Soroosh's example Generic.xaml file, I wrapped the TextBlock in such a Viewbox:
<Button >
<StackPanel Orientation="Horizontal">
<Image Margin="2 0"
Source="{TemplateBinding Image}"
Width="{TemplateBinding ImageWidth}"
Height="{TemplateBinding ImageHeight}"
Visibility="{TemplateBinding Image,Converter={StaticResource VisibilityConvertor}}"
VerticalAlignment="Center"/>
I added--> <Viewbox StretchDirection="DownOnly" Stretch="Fill">
<TextBlock Text="{TemplateBinding Content}"
VerticalAlignment="Center"/>
I added--> </Viewbox>
</StackPanel>
</Button>
This produced exactly the same clipped button text. Just experimenting, I tried forcing the Viewbox to have a fixed width...
<Viewbox StretchDirection="DownOnly" Stretch="Fill" Width="60">
...which produced this:
...which shows the capability of the Viewbox, if only it could somehow know its available width when it's inside the StackPanel.
I did note that if I wrap the Viewbox around the whole StackPanel, it successfully auto-shrinks the entire content of the StackPanel:
<Button >
<Viewbox StretchDirection="DownOnly" Stretch="Fill" Width="60">
<StackPanel Orientation="Horizontal">
<Image Margin="2 0"
Source="{TemplateBinding Image}"
Width="{TemplateBinding ImageWidth}"
Height="{TemplateBinding ImageHeight}"
Visibility="{TemplateBinding Image,Converter={StaticResource VisibilityConvertor}}"
VerticalAlignment="Center"/>
<TextBlock Text="{TemplateBinding Content}"
VerticalAlignment="Center"/>
</StackPanel>
</Viewbox>
</Button>
...which produces very nearly what I want:
...but both the image and text are shrunk, and I want only the text shrunk.
How can I make the Viewbox, wrapping only the TextBox, know its available width (and height, I suppose) from within a cell of the StackPanel?
This is a common problem. The solution is simply to not use a StackPanel to do any kind of layout that requires re-sizing of child controls. It's simply not the correct Panel for the job. Instead, try using a Grid panel, which will resize its child controls. The StackPanel control is really only good for the most basic of layout duties... try anything more adventurous and you'll find yourself getting these issues.
One other alternative is to use the TextBlock.TextTrimming Property to trim the text instead... you could put the full text into a ToolTip too.
I am using ScaleTransform to change the size of a UserControl on a Canvas. It works perfectly until I use the ItemsControl Control.
The problem is that I need the scaling to be centered, the UserControl should not "move". As soon as it is inside the ItemsControl, the item Scales on Position x=0, y=0 instead of the center.
Would be great to know what I am doing wrong!
Here is some XAML showing it does not work (there is a single item in DataSource, nothing special it only displays a red rectangle on the window).
// This slider is used to scale the Grid inside the ItemsControl.
<Slider x:Name="pointResizeSlider" Margin="10,10,10,0" VerticalAlignment="Top" Maximum="7" Value="1"/>
// The items Control.
<ItemsControl Name="icTest" Background="Blue" Width="200" Height="200">
<ItemsControl.ItemTemplate>
<DataTemplate>
// For simplicity I am using a simple 100x100 Grid. This will get scaled.
<Grid Margin="0 0 5 5" Width="100" Height="100" Background="Red">
<Grid.LayoutTransform>
<TransformGroup>
<ScaleTransform
// This would make it pretty obvious, if it would work.
// Shows no effect.
CenterX="1000"
CenterY="1000"
ScaleX="{Binding Path=Value, ElementName=pointResizeSlider}"
ScaleY="{Binding Path=Value, ElementName=pointResizeSlider}" />
</TransformGroup>
</Grid.LayoutTransform>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Edit
Using RenderTransform works in this case, but I have to calculate the ActualSize of the UserControl (which does not work right now with RenderTransform). Why does LayoutTransform not work in this case?
I have a horizontal ScrollViewer that contains a single StackPanel, which is initially empty. UserControls are created on button-click, and added to the StackPanel. The code looks something like this:
<ScrollViewer Grid.Column="1" Grid.Row="0" RequestedTheme="Dark" ScrollViewer.HorizontalScrollMode="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollMode="Disabled" ScrollViewer.VerticalScrollBarVisibility="Hidden">
<StackPanel x:Name="Container" HorizontalAlignment="Left" VerticalAlignment="Top" Width="Auto">
<!--User controls added here dynamically-->
</StackPanel>
</ScrollViewer>
As you can see the ScrollViewer is itself in a larger Grid. Now I would like a Polygon to be added to this ScrollViewer, but I cannot add it as a child directly, since "Content can only be set once". If I add it to the StackPanel in code-behind (after setting Canvas left, top and ZIndex), the UserControls are added below the Polygon. I want them to be under or over, either will do. Is this even possible? Right now, my Polygon shares the same Grid Row and Column as the ScrollViewer. Here is my Polygon:
<Polygon x:Name="Gripper" Grid.Column="1" Grid.Row="0" Points="0,0 0,730 -30,750 -30,800 30,800 30,750 0,730 0,100" Stroke="#DEDEDE" StrokeThickness="1" Opacity="1.0" ManipulationMode="TranslateX" ManipulationDelta="Gripper_ManipulationDelta">
<Polygon.Fill>
<SolidColorBrush Color="#FFFFFF" Opacity="0.9"/>
</Polygon.Fill>
<Polygon.RenderTransform>
<CompositeTransform />
</Polygon.RenderTransform>
</Polygon>
I am okay with adding it in XAML or C#, but I think I would prefer to do it in C# since I would like to change the points based on the size of the screen.
Put another container control between the StackPanel and the Polygon. An intermediate Grid will let you control their placement by row and column as normal. An intermediate StackPanel will let the Container stack and Polygon stack separately from the items within the Container stack:
<ScrollViewer>
<Grid>
<StackPanel x:Name="Container" HorizontalAlignment="Left" VerticalAlignment="Top" Width="Auto">
<!--User controls added here dynamically-->
</StackPanel>
<Polygon />
</Grid>
</ScrollViewer>
So I have a rather interesting question. I have a viewbox that has a few elements in it (a custom user control for an image, a canvas, a label, and a textbox). What I want is to try and have all elements scale with the viewbox, but I want the label and the textbox to have a "Max Size." I have tried using a max width and height on these controls but they seem to ignore it. If someone could take a look at my code below an slap me for what I am doing wrong that would be appreciated.
<Viewbox Name="myViewBox" Stretch="Uniform">
<!--Grid used to track mouse movements in this element for other reasons -->
<Grid Name="grdViewboxGrid" MouseMove="trackMouse">
<Canvas Name="cvsViewboxCanvas" MinWidth="270" MinHeight="270"
VerticalAlignment="Top" HorizontalAlignment="Center"
Panel.ZIndex="1" Background="Black"
MouseUp="Canvas_MouseUp"
MouseMove="Canvas_MouseMove">
<Grid>
<!--Would rather not post here for Intellectual Property reasons-->
<!-- Extension of the image control -->
<CustomImageUserControl />
<Grid>
<Grid Width="{Binding LabelWidthPercentage}"
MaxWidth="50"
Height="{Binding LabelHeightPercentage"
MaxHeight="26"
SnapsToDevicePixels="True" VerticalAlignment="Top"
HorizontalAlignment="Left" Margin="5" IsHitTestVisible="False">
<Label Name="lblViewboxLabel" HorizontalAlignment="Left"
Padding="5,5,5,0" Margin="0,5,0,0"
Style="{x:Null}"
Content="{Binding lblContent}" />
</Grid>
<Grid>
<Grid Width="{Binding TextBoxWidthPercentage}"
MaxWidth="156"
Height="{Binding TextBoxHeightPercentage}"
MaxHeight="45"
SnapsToDevicePixels="True" Vertical="Top"
HorizontalAlignment="Right" Margin="5" IsHitTestVisible="False">
<Border Style="{DynamicResource CustomBorder}" />
<Grid>
<Textbox Name="txtViewboxTextBox" Text="{Binding txtViewbox}" />
</Grid>
</Grid>
</Grid>
</Grid>
</Grid>
</Canvas>
</Grid>
</Viewbox>
If I am not including something that is needed please let me know and I will update my question. Any help would be greatly appreciated this is now day 4 on this issue sadly :-(
I am not sure why you need so many overlapping Grids, but I hope that I can answer your question nevertheless:
In order to have the label left of the text box and to assign a maximum width to each of these two controls, use a Grid with two columns and set the MaxWidth property for each column. Then, assign the label to the left column (the one with index 0) and assign the text box to the right column (index 1). The corresponding code fragment looks like this:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MaxWidth="30"/>
<ColumnDefinition MaxWidth="156" MinWidth="30"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" x:Name="lblViewboxLabel" HorizontalAlignment="Left" Foreground="Yellow"
Padding="5,5,5,0" Margin="0,5,0,0"
Style="{x:Null}"
Content="{Binding lblContent}" />
<TextBox Grid.Column="1" x:Name="txtViewboxTextBox" Text="{Binding txtViewbox}" Background="Orange"/>
</Grid>
I also have assigned a MinWidth to the right column; this is necessary to make sure that the text box does not completely disappear if it contains no text.
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>