OOB Silverlight and content scale on window resize - silverlight

Good morning,
I faced problem when doing scaleTransform on the content when OOB Silverlight application's window gets resized. The code looks very simple
xaml
<UserControl x:Class="SilverlightApplication1.MainPage"
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"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="Aquamarine" RenderTransformOrigin="0,0">
<Rectangle Fill="Aqua" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
<Grid VerticalAlignment="Center" HorizontalAlignment="Center" Height="150">
<TextBlock FontSize="20" Text="Hello World" Margin="5" VerticalAlignment="Top" HorizontalAlignment="Center"/>
<Button Content="Button" VerticalAlignment="Bottom" HorizontalAlignment="Center"/>
</Grid>
</Grid>
</UserControl>
C#
public MainPage()
{
InitializeComponent();
SizeChanged += MainPage_SizeChanged;
}
void MainPage_SizeChanged(object sender, SizeChangedEventArgs e)
{
ScaleTransform scaleTransform = new ScaleTransform();
scaleTransform.ScaleX = (Application.Current.MainWindow.Width / 500f);
scaleTransform.ScaleY = (Application.Current.MainWindow.Height / 500f);
scaleTransform.CenterX = 0;
scaleTransform.CenterY = 0;
// this.RenderTransform doesn't work either.
LayoutRoot.RenderTransform = scaleTransform;
}
The content gets scaled when the main window is resized, but, for some reason, I see white background of the window when scaling down. It seems that the content is scaled down faster than window and I don't know what I am doing wrong. The code seems logical and should work, shouldn't it?

The LayoutTransformer saved my day. I have changed the code and xaml as follows and everything works now. Code may need a little tweaking though.
xaml
<UserControl x:Class="SilverlightApplication1.MainPage"
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:layout="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Layout.Toolkit"
mc:Ignorable="d"
d:DesignHeight="500" d:DesignWidth="500">
<layout:LayoutTransformer x:Name="LayoutTransformer">
<layout:LayoutTransformer.Content>
<Grid x:Name="LayoutRoot" Background="AntiqueWhite">
<Rectangle Fill="Aqua" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
<Grid VerticalAlignment="Center" HorizontalAlignment="Center" Height="150">
<TextBlock FontSize="20" Text="Hello World" Margin="5" VerticalAlignment="Top" HorizontalAlignment="Center"/>
<Button Content="Button" VerticalAlignment="Bottom" HorizontalAlignment="Center"/>
</Grid>
</Grid>
</layout:LayoutTransformer.Content>
<layout:LayoutTransformer.LayoutTransform>
<ScaleTransform x:Name="ContentScale" CenterX="0" CenterY="0" ScaleX="1" ScaleY="1" />
</layout:LayoutTransformer.LayoutTransform>
</layout:LayoutTransformer>
</UserControl>
C#
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
SizeChanged += MainPage_SizeChanged;
}
void MainPage_SizeChanged(object sender, SizeChangedEventArgs e)
{
double yScale = ActualHeight / 500f;
double xScale = ActualWidth / 500f;
double value = GetScale(xScale, yScale);
ContentScale.ScaleX = value;
ContentScale.ScaleY = value;
LayoutTransformer.ApplyLayoutTransform();
}
private double GetScale(double xScale, double yScale)
{
return Math.Max(0.1, Math.Min(xScale, yScale));
}
}

Related

UserControl child fill Window

I have a UserControl that is a portion of a wpf window.
<Window>
<Grid>
<!--some other display elements would be here-->
<local:MyUserControl x:Name="Foo" Padding="0,42,0,50"/>
</Grid>
</Window>
Inside MyUserControl I have an element that is a gallery that is normally hidden, but when visible, it should fill the entire screen.
<UserControl>
<Grid>
<!--main display elements would be here-->
<Grid Name="Gallery" Visibility="Hidden">
<Rectangle Fill="Black" Opacity="0.75"/>
<TextBlock Name="GalleryLabel" Foreground="White" TextAlignment="Center">Current Image Title</TextBlock>
<Button Name="CloseGallery" Style="{DynamicResource WhiteTextButton}" Margin="0,0,0,0" Height="25" VerticalAlignment="Top" HorizontalAlignment="Right" Width="25" Click="GalleryClose_OnClick">X</Button>
<Image Name="GalleryImage" Margin="25"/>
</Grid>
</Grid>
</UserControl>
How can I set the Gallery to fill the entire Window rather than just the UserControl?
I was able to get it to work by adding Margin="0,-42,0,-50" to Gallery, but I don't like that solution. I would rather do something that doesn't involve hard-coding values in the UserControl so that I would be able to have more flexiblility in using it.
Normally it looks like:
where the green Foo area is MyUserControl, and the rest of the things in the window are other elements.
At certain points, I have a gallery display an image, which should fill the entire screen like:
which should fill the entire screen and have a black opaque overlay, along with an image displayed on top of the overlay.
Remove the Padding...
You can use:
<local:MyUserControl x:Name="Foo" VerticalAlignment="Stretch" HorizontalAligment="Stretch"/>
EDIT
I may admit that I still am not sure what you want. But I made something which does the same as you showed in the pictures. But be aware that this as an opinion based question, and the answer is my opinion, there are a lot of ways to achieve this. And this is only one of them:
MainWindow
<Window x:Class="MyProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:myProject="clr-namespace:MyProject"
Title="MainWindow" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border Background="Gainsboro" Grid.Row="0">
<StackPanel Orientation="Horizontal">
<Button Content="Show gallery" Width="100" Margin="10"/>
<Button Content="Do something else" Width="150" Margin="10"/>
</StackPanel>
</Border>
<myProject:SomeOtherStuff Grid.Row="1" />
<Border Grid.Row="2" Background="Gainsboro">
<StackPanel Orientation="Horizontal">
<Label Content="Buttom area, can be used for something else"/>
</StackPanel>
</Border>
<myProject:GalleryUserControl x:Name="GalleryUserControl" Grid.Row="0" Grid.RowSpan="3" Visibility="Hidden"/>
</Grid>
SomeOtherStuff UserControl
<UserControl x:Class="MyProject.SomeOtherStuff"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid Background="Green">
<Label VerticalAlignment="Center" HorizontalAlignment="Center" Content="Foo" FontSize="30" FontFamily="Verdana"/>
</Grid>
Gallery UserControl
<UserControl x:Class="XamDataGrid.GalleryUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="500" Width="800">
<Grid Background="#99000000">
<TextBlock Text="Currect image title" Foreground="White" TextAlignment="Center" VerticalAlignment="Top" HorizontalAlignment="Stretch"/>
<Button Name="CloseGallery" Margin="0,0,0,0" Content="X" Height="25" VerticalAlignment="Top" HorizontalAlignment="Right" Width="25" Click="GalleryClose_OnClick"/>
<Image Margin="30"/>
</Grid>
An Adorner will be best for you. As it floats above everything else and remains outside the VisualTree too.
UserControl2
<UserControl2 ...>
<Grid>
<Grid Background="#FF709FA6" Opacity="0.3" Width="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}}"
Height="{Binding ActualHeight, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}}">
</Grid>
<Grid Width="600" Height="700">
<Grid.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF37DAEA" Offset="0"/>
<GradientStop Color="#FFE84242" Offset="1"/>
</LinearGradientBrush>
</Grid.Background>
<!-- Gallery controls -->
<Button Content="Welcome to Gallery" HorizontalAlignment="Left" IsHitTestVisible="True" Margin="112,126,0,0" VerticalAlignment="Top" Height="68" FontSize="48" Click="Button_Click_1"/>
<TextBlock HorizontalAlignment="Left" Margin="83,42,0,0" TextWrapping="Wrap" Text="UserControl2" VerticalAlignment="Top" Foreground="#FF1B0D0D"/>
</Grid>
</Grid>
</UserControl2>
UserControl1
Code :
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
// get root Window
DependencyObject current = LogicalTreeHelper.GetParent(this);
while (!(current is Window))
current = LogicalTreeHelper.GetParent(current);
Window root = current as Window;
IEnumerable children = LogicalTreeHelper.GetChildren(root);
Panel p = null;
foreach (var child in children)
{
p = child as Panel; // get first container panel in Window
break;
}
// Create UserControl2 to add to the adorner
UserControl2 ctrlGallery = new UserControl2();
AdornerLayer layer = AdornerLayer.GetAdornerLayer(p);
GalleryAdorner adorner = new GalleryAdorner(p, ctrlGallery);
layer.Add(adorner);
}
}
public class GalleryAdorner : Adorner
{
private Control _child;
VisualCollection collection;
public GalleryAdorner(UIElement elem, Control child)
: base(elem)
{
collection = new VisualCollection(this);
_child = child;
collection.Add(_child);
}
protected override int VisualChildrenCount
{
get
{
return 1;
}
}
protected override Visual GetVisualChild(int index)
{
if (index != 0) throw new ArgumentOutOfRangeException();
return collection[0];
}
protected override Size MeasureOverride(Size constraint)
{
_child.Measure(constraint);
return _child.DesiredSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
_child.Arrange(new Rect(new Point(0, 0), finalSize));
return new Size(_child.ActualWidth, _child.ActualHeight);
}
}

Trigger a fade out animation when slider's value changes

I'm trying to bind the Opacity property of a Rectangle shape to the Slider's value. So that when its value passes 2, the Rectangle fades out and when we decrease the slider's value and it passes the value of 2 it appears again with a fade in animation. What's the best practice to do this?
<Window x:Class="Layout.AnimateOpacity"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="AnimateOpacity" Height="300" Width="300">
<DockPanel VerticalAlignment="Center" HorizontalAlignment="Center"
Height="300" Width="300">
<Canvas DockPanel.Dock="Top"
Width="300" Height="200"
Background="Black">
<Rectangle x:Name="myRectangle"
Width="100" Height="100"
Canvas.Left="100" Canvas.Top="60"
Fill="Yellow">
</Rectangle>
</Canvas>
<Slider x:Name="mySlider" DockPanel.Dock="Bottom"
Height="30" Width="250"
Value="1" Maximum="3" Minimum="0" />
</DockPanel>
</Window>
Hook ValueChanged event of slider and there you can do animation based on new and old value of slider.
XAML:
<Slider x:Name="mySlider" DockPanel.Dock="Bottom"
Height="30" Width="250"
Value="1" Maximum="3" Minimum="0"
ValueChanged="mySlider_ValueChanged" />
Code behind:
private void mySlider_ValueChanged(object sender,
RoutedPropertyChangedEventArgs<double> e)
{
if (e.NewValue > 2 && e.OldValue <= 2)
{
DoubleAnimation fadeOutAnimation = new DoubleAnimation(0.0,
new Duration(TimeSpan.FromSeconds(1)));
myRectangle.BeginAnimation(Rectangle.OpacityProperty, fadeOutAnimation);
}
else if(e.NewValue < 2 && e.OldValue >= 2)
{
DoubleAnimation fadeInAnimation = new DoubleAnimation(1.0,
new Duration(TimeSpan.FromSeconds(1)));
myRectangle.BeginAnimation(Rectangle.OpacityProperty, fadeInAnimation);
}
}

Dynamically generate textbox to match sum

I'm trying to generate Dynamic Text Box
Starting with two textboxes.
if the value is less than the value in the first textbox then generate another textbox dynamically and let the user enter more values.
This has to be done till the sum of the values of all the text boxes from the second to the last one generated becomes equal to the value of first textbox.
Of course other things need to be generated with the textboxes as well like lables etc. and positioned correctly so i thought of using a grid and generate the grid dynamically but above that i'm lost.
Any Help?
Thanks
i used a scrollviewer with the following code
<ScrollViewer Margin="8,8,8,14.417" Grid.Row="4" Grid.ColumnSpan="5" VerticalScrollBarVisibility="Hidden">
<Grid Margin="8" Grid.Row="4" Grid.ColumnSpan="4" x:Name="amtGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="103"/>
<ColumnDefinition Width="Auto" MinWidth="324"/>
<ColumnDefinition Width="Auto" MinWidth="218"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ComboBox x:Name="crdrnextrows" Margin="32.367,8,8,7.423" SelectedIndex="1" />
<ComboBox Background="#FFC6C3C6" Margin="8" x:Name="comboboxCr" GotKeyboardFocus="comboboxCr_GotKeyboardFocus" Grid.Column="1"/>
<TextBox Background="#FFC6C3C6" Foreground="White" IsEnabled="True" Margin="7.973,8,8,8" x:Name="txtBoxam1" Grid.Column="2" LostFocus="txtBoxam1_LostFocus"/>
<TextBox Background="#FFC6C3C6" Foreground="White" IsEnabled="True" Margin="8,8,33.972,8" x:Name="txtBoxamt2" Grid.Column="3" LostFocus="textBox4_LostFocus"/>
</Grid>
</ScrollViewer>
There is another textbox above that with similar code but without the scroll viewer, now what i was thinking was to dynamically create instances of the grid shown in the scrollviewer as many times as need to make them equal.
Is it possible to create new instances of the same grid and add them to the scollviewer dynamically with code?
Thanks
Looking at the additional information that you gave and given the complexity of the object you are wanting to create, a UserControl would probably be the best fit. This code is an example using a DoubleClick to show how to add the UserControl to your ScrollViewer. You will need to expose properties in the UserControl in order to get the information from your TextBoxes otherwise the Code should be simular to my earlier answer.
i.e:
UserControl Xaml
<UserControl x:Class="WpfApplication1.UserControl1"
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"
d:DesignHeight="70" d:DesignWidth="985">
<Grid Margin="8" Grid.Row="4" Grid.ColumnSpan="4" x:Name="amtGrid" Height="40">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="103"/>
<ColumnDefinition Width="Auto" MinWidth="324"/>
<ColumnDefinition Width="Auto" MinWidth="218"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ComboBox x:Name="crdrnextrows" Margin="32.367,8,8,7.423" SelectedIndex="1" />
<ComboBox Background="#FFC6C3C6" Margin="8" x:Name="comboboxCr" GotKeyboardFocus="comboboxCr_GotKeyboardFocus" Grid.Column="1"/>
<TextBox Background="#FFC6C3C6" Foreground="White" IsEnabled="True" Margin="7.973,8,8,8" x:Name="txtBoxam1" Grid.Column="2" LostFocus="txtBoxam1_LostFocus"/>
<TextBox Background="#FFC6C3C6" Foreground="White" IsEnabled="True" Margin="8,8,33.972,8" x:Name="txtBoxamt2" Grid.Column="3" LostFocus="txtBoxamt2_LostFocus"/>
</Grid>
</UserControl>
Window Xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="123" Width="1098" xmlns:my="clr-namespace:WpfApplication1" MouseDoubleClick="Window_MouseDoubleClick">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel Name="stackPanel1" VerticalAlignment="top" HorizontalAlignment="Left" >
<my:UserControl1 x:Name="userControl11" Width="1077" />
</StackPanel>
</ScrollViewer>
</Window>
Main Window Code
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
UserControl1 newUserControl = new UserControl1();
newUserControl.Width = userControl11.Width;
newUserControl.Height = userControl11.Height;
stackPanel1.Children.Add(newUserControl);
}
}
Here is a basic idea, I am using a StackPanel to hold the TextBox's you may want to use a DockPanel to hold your labels and etc and add that to the StackPanel.
Xaml
<Window x:Class="WpfApplication1.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>
<StackPanel Name="myContainer">
<TextBox Height="23" HorizontalAlignment="Left" Margin="10,10,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" KeyDown="textBox1_KeyDown" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="10,10,0,0" Name="textBox2" VerticalAlignment="Top" Width="120" KeyDown="textBox2_KeyDown"/>
</StackPanel>
</Grid>
</Window>
Code
public partial class MainWindow : Window
{
Collection<Control> myControls = new Collection<Control>();
public MainWindow()
{
InitializeComponent();
myControls.Add(textBox2);
}
private void textBox2_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
int temp;
int sum;
sum = 0;
foreach (TextBox tb in myControls)
{
if (int.TryParse(tb.Text, out temp))
{
sum += temp;
}
}
int test = 0;
if (int.TryParse(textBox1.Text, out test))
{
if (sum < test)
{
TextBox newtb = new TextBox();
newtb.Width = ((TextBox)sender).Width;
newtb.Height = ((TextBox)sender).Height;
newtb.Margin = new Thickness(((TextBox)sender).Margin.Left, ((TextBox)sender).Margin.Top , ((TextBox)sender).Margin.Right , ((TextBox)sender).Margin.Bottom);
newtb.HorizontalAlignment = ((TextBox)sender).HorizontalAlignment;
newtb.KeyDown += new KeyEventHandler(textBox2_KeyDown);
myContainer.Children.Add(newtb);
myControls.Add(newtb);
newtb.Focus();
}
else
this.Background = Brushes.LightBlue;
}
}
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
textBox2.Focus();
}
}
}
Pass the collection to the item. Then in the set add to the collection as necessary.
public class dynamicInts
{
private int dInt;
private ObservableCollection<DynamicInt> dynamicInts
public int DInt
{
get { return dInt; }
set
{
value = dInt;
int sumInt;
foreach (DynamicInt di in dynamicInts) sumInt += di.Dint)
if (sumInt < 2*dynamicInts) dynamicInts.add(newdynamicInts ...

wp7 slider hangs up

I am trying to use a slider control. It's just the simple control. Nothing fancy. But I run into an issue that is confusing me.
If I put the control on a test page (blank with nothing else) and navigate to it immediately after the app launches , I can slide it around perfectly. But if I navigate to another page first and then to the test page. I get a very weird behavior. The slider control moves in steps. It seems as if it hangs up or is losing focus.
I'm using wp7.1 and I've tested in the emulator and on the phone. Both give me the same result. I don't even know where to start solving this, but i definitely need a slider and for it to move smoothly.
Any ideas?
revised to include xaml:
<phone:PhoneApplicationPage
x:Class="WP7ListBoxSelectedItemStyle.TestPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
xmlns:local="clr-namespace:WP7ListBoxSelectedItemStyle"
xmlns:my="clr-namespace:colordata_controls;assembly=colordata_controls"
shell:SystemTray.IsVisible="True" xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit">
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="IPO" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="Test" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="8,17,16,-17">
<Slider Height="84" HorizontalAlignment="Left" Margin="10,10,0,0" Name="slider1" VerticalAlignment="Top" Width="460" />
</Grid>
</Grid>
here is a link to a video of it in action in the emulator. https://vimeo.com/36428677
so, I still don't know why the slider sticks that way, but in order to keep moving forward I created my own slider. Hopefully this code helps someone else.
xaml:
<UserControl
x:Name="userControl"
x:Class="controls.pSlider"
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"
d:DesignWidth="76" d:DesignHeight="400" Background="Gray" Foreground="White">
<Grid x:Name="LayoutRoot" Background="Transparent" MouseMove="LayoutRoot_MouseMove" MouseLeftButtonDown="LayoutRoot_MouseLeftButtonDown">
<Grid.RowDefinitions>
<RowDefinition Height="10"/>
<RowDefinition/>
<RowDefinition Height="10"/>
</Grid.RowDefinitions>
<Rectangle x:Name="colorBar" Margin="20,6" Width="10" Fill="{Binding Background, ElementName=userControl}" Grid.Row="1"/>
<Grid x:Name="g_container" Grid.Row="1" Margin="0,1,0,13">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="0"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid x:Name="g_thumb" Height="0" VerticalAlignment="Top" Grid.Row="1">
<Canvas Height="0" VerticalAlignment="Top">
<Path Data="M0,0 L1,0 L1.2,0.5 L1,1 L0,1 z" Margin="0" Stretch="Fill" UseLayoutRounding="False" Width="33" RenderTransformOrigin="0.5,0.5" StrokeThickness="0" Fill="{Binding Foreground, ElementName=userControl}" Height="12" d:LayoutOverrides="VerticalAlignment"/>
<Path Data="M0.3,0.5 L0.5,0 L1.5,0 L1.5,1 L0.5,1 z" Margin="0" Stretch="Fill" UseLayoutRounding="False" Width="33" RenderTransformOrigin="0.5,0.5" StrokeThickness="0" Fill="{Binding Foreground, ElementName=userControl}" Height="12" Canvas.Left="43" d:LayoutOverrides="VerticalAlignment"/>
</Canvas>
</Grid>
<Rectangle x:Name="r_lifter" Margin="0" Grid.Row="2" Height="188" StrokeThickness="0"/>
</Grid>
</Grid>
code:
namespace controls {
public partial class pSlider : UserControl {
public event RoutedEventHandler ValueChanged;
public static readonly DependencyProperty MaxProperty =
DependencyProperty.Register("Maximum", typeof(double), typeof(pSlider), new PropertyMetadata(100.0));
public double Maximum {
get { return (double)GetValue(MaxProperty); }
set { SetValue(MaxProperty, value); }
}
public static readonly DependencyProperty MinProperty =
DependencyProperty.Register("Minimum", typeof(double), typeof(pSlider), new PropertyMetadata(0.0));
public double Minimum {
get { return (double)GetValue(MinProperty); }
set { SetValue(MinProperty, value); }
}
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(double), typeof(pSlider), new PropertyMetadata(50.0));
public double Value {
get { return (double)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public pSlider() {
InitializeComponent();
Loaded += new RoutedEventHandler(pSlider_Loaded);
}
void pSlider_Loaded(object sender, RoutedEventArgs e) {
if (Value > Maximum)
Value = Maximum;
else if (Value < Minimum)
Value = Minimum;
double min = 0;
double max = g_container.ActualHeight;
r_lifter.Height = Value / (Maximum - Minimum) * (max - min);
}
private Point Position;
private void LayoutRoot_MouseMove(object sender, MouseEventArgs e) {
Point newPosition = e.GetPosition((UIElement)sender);
double delta = newPosition.Y - Position.Y;
double temp = r_lifter.Height - delta;
if (temp > g_container.ActualHeight)
r_lifter.Height = g_container.ActualHeight;
else if (temp < 0)
r_lifter.Height = 0;
else
r_lifter.Height = temp;
double min = 0;
double max = g_container.ActualHeight;
Value = r_lifter.Height / (max - min) * (Maximum - Minimum);
Value = Math.Floor(Value);
RoutedEventHandler handler = ValueChanged;
if (handler != null)
handler(this, e);
Position = e.GetPosition((UIElement)sender);
}
private void LayoutRoot_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
Position = e.GetPosition((UIElement)sender);
}
}
}

Changing RenderTransformOrigin property of rotated object

how can I make a rotated object stand still when its RenderTransformOrigin property is changed? After running the code below, you can notice by rotating the object (the slider does that), changing the origin of rotation (the button) and rotating it again, that the object slightly moves. What I'm trying to achieve is being able to rotate the object against different points without it moving around whenever I try to switch between them.
<UserControl x:Class="ObjrctRotation.MainPage"
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"
d:DesignHeight="300" d:DesignWidth="400">
<Canvas x:Name="C" Background="White">
<Path x:Name="thing" RenderTransformOrigin="0,0" Stretch="Fill" Stroke="Black" StrokeThickness="2" Height="93.153" HorizontalAlignment="Left" VerticalAlignment="Top" Width="106.357" UseLayoutRounding="False" Data="M48.723255,124.82815 C41.00029,80.999809 81.000046,65.000069 112.99985,89.000092 C144.99965,113.00011 168.9996,169.00061 136.99989,169.0002 C105.00018,168.99979 104.9999,145.00015 81.000053,145.00015 C57.000206,145.00015 56.44622,168.65649 48.723255,124.82815 z" Canvas.Left="69" Canvas.Top="24" />
<Slider Value="0" Minimum="0" Maximum="360" Width="100" Margin="300,0,0,272" ValueChanged="Slider_ValueChanged" />
<TextBlock x:Name="test" Width="100" Height="20" Canvas.Left="300" Canvas.Top="24" />
<Button Canvas.Left="300" Canvas.Top="24" Content="ChangeCenter" Height="20" Name="button1" Width="100" Click="button1_Click"/>
</Canvas>
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
RotateTransform rotate = new RotateTransform()
{
Angle=e.NewValue
};
thing.RenderTransform = rotate;
}
private void button1_Click(object sender, RoutedEventArgs e)
{
thing.RenderTransformOrigin = new Point(thing.RenderTransformOrigin.X + 0.2, thing.RenderTransformOrigin.Y + 0.2);
}
}
Set the RenderTransformOrigin="0,0" to RenderTransformOrigin="0.5,0.5" so that the transform origin is in the middle of the object you wish to rotate.

Resources