The .To function in Silverlight - silverlight

this.onePX.To = 64;
With the XAML:
<Rectangle Width="32" Height="32" Fill="Black" x:Name="onePX" Grid.Column="0" Grid.Row="0">
<Rectangle.RenderTransform>
<TranslateTransform />
</Rectangle.RenderTransform>
</Rectangle>
but for some reason, it returns with:
System.Windows.Shapes.Rectangle does not contain a definition for "To" and no extension method "To"...
Any idea why this could be happening, I tried to Google it, but searching for ".To" doesn't exactly yield accurate results ^.^

A Silverlight Rectangle does not have a "To" member (or method etc), so the compiler is quite right.
What are you actually trying to do the the Rectangle? That might result in better answers.
Edit 2
Ok, if you want to move a rectangle (on a pixel basis I assume as you said to an X,Y coordinate) you 1st need to parent it under a Canvas. Only a canvas renders children on a pixel basis.
Secondly to actually move a child of a Canvas, you need to set the attached properties Canvas.LeftProperty and Canvas.TopProperty.
You can either do this using the static methods Canvas.SetLeft(onePX, newValue) and Canvas.SetTop(onePx, newValue) (which take the child object and new values as parameters), or you can use the other SetValue syntax which looks like this.onePX.SetValue(Canvas.LeftProperty, newValue) and this.onePx.SetValue(Canvas.LeftProperty, newValue) etc.
The first static-method syntax is usually shorter and easier on the eyes :)
Hope this helps.

Related

Can you set a Canvas the Background of an element in WPF?

Apologies if this has been asked but I can't find the answer. I have a couple of items (Windows, UserControls and DockPanels) that need dynamic backgrounds.
A Canvas object suits my needs well for the dynamic drawing, however, what I can't figure out is how (or even if) I can set a <Canvas> object as the value of a Background for a control object.
Can this be done and if yes, how?
Yes you can do that.
<Window.Background>
<VisualBrush>
<VisualBrush.Visual>
<Rectangle Width="50" Height="50" Fill="Red"></Rectangle><!-- Replace this with a reference to your Canvas-->
</VisualBrush.Visual>
</VisualBrush>
</Window.Background>
Code is referenced from this site there is a lot more that you can do with that background as well. Like set clipping etc ...
Note
Because you haven't specified the language you are developing it, I provided answer in the language I use namely C#, I don't use VB.
Dou you want to set the Background property of a control with the "contents" of a Canvas already populated with elements?
If so, yes; it's possible to accomplish this task creating a Brush from your Canvas. To do it, you need the VisualBrush class. In VB.NET, use something like this:
Dim oBrush As New VisualBrush(myCanvas)
myControl.Background = oBrush
Good luck, good code

Animating from a point other than the left side

I have an animation problem that I'm not sure how to Google or find a solution for. I'm trying to basically create a wrapping Marquee. I do this by having the following within a canvas:
|---Section A---|---Section B---|Section C---|
The animation begins with the left side of section B on the right side of the screen, and ends when the right side of section B hits the left side of the screen. Sections A and C are a mirror image of Section B, which creates the "wrap around" effect. When the animation ends, I move everything to the right the exact width of Section B. To the user, nothing appears to have happened .. it's all just wrapping around.
The problem is this ... some of the items in the marquee can be hidden, or can change size. So if you hide an item, the item is hidden from all three sections. Since things are being hidden in Section A, and all the sections are sized dynamically, the entire marquee moves to the left.
Is there any way to "anchor" the animation at a spot, say, in the middle of Section B, so that when items are hidden in section A, it doesn't slide sections B and C over? Instead, I want Section A to move right to fill in the space.
Edit: Let me rephrase ... because this is confusing.
I have a canvas, which contains a stackpanel, which contains three more stack panels. These three stack panels are actually copies of the same information, which gives the illusion of a marquee that wraps around when I animate. When items are added/removed in the marquee, those items in the stack panel change, which adjusts the overall size of the stack panel, which adjusts the size of the canvas. What I'd like to know, is if I can "anchor" a specific location within the stackpanel. Can I "anchor" on the first item in the 2nd stackpanel copy?
To answer what APPEARS to be the primary question:
Is there a way to animation the position of a canvas using something
other than the Canvas.Left property
Set the RenderTransform property of the Canvas to a TranslateTransform and animate the TranslateTransform.X Property:
<Canvas x:Name="myCanvas" RenderTransformOrigin="0.5,0.5">
<Canvas.RenderTransform>
<TranslateTransform X="0"/>
</Canvas.RenderTransform>
</Canvas>
Then in code:
EDIT: The second parameter of this method call should be of type DoubleAnimation, not Duration. I must have been sleeping at my desk when I typed this. Sorry.
(TranslateTransform)MyCanvas.RenderTransform.BeginAnimation(TranslateTransform.XProperty, new Duration(TimeSpan.FromSeconds(3)));
I hope this helps.
My other answer is becoming obsolete as you elaborate on your desired behavior, so forgive me for posting a second. Based on my latter comments on the above answer, consider the following example:
<Canvas x:Name="LayoutRoot">
<Grid x:Name="MarqueePanels">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="0" Height="{Binding ElementName=PrimaryMarquee, Path=ActualHeight}" Width="{Binding ElementName=PrimaryMarquee, Path=ActualWidth}">
<Rectangle.Fill>
<VisualBrush Visual="{Binding ElementName=PrimaryMarquee}"/>
</Rectangle.Fill>
</Rectangle>
<StackPanel Grid.Column="1" x:Name="PrimaryMarquee">
<TextBlock Text="Marquee Item 1"/>
<TextBlock Text="Marquee Item 2"/>
<TextBlock Text="Marquee Item 3"/>
</StackPanel>
<Rectangle Grid.Column="2" Height="{Binding ElementName=PrimaryMarquee, Path=ActualHeight}" Width="{Binding ElementName=PrimaryMarquee, Path=ActualWidth}">
<Rectangle.Fill>
<VisualBrush Visual="{Binding ElementName=PrimaryMarquee}"/>
</Rectangle.Fill>
</Rectangle>
</Grid>
</Canvas>
As I mentioned above, setting the Visibility of any of the TextBox elements to Hidden will not cause the StackPanel parent to resize, however using Visibility.Collapsed WILL force an Arrange pass of the parent panel. So if you truly NEED to use a StackPanel to contain the visual elements, then I recommend based on your comments above using Visibility.Hidden in lieu of Visibility.Collapsed.
Also notice the use of VisualBrush to replicate the Marquee content. This will simplify the code, and ensure that all 3 visuals always match (with the exception of whatever positioning or transformation you apply to the Rectangle objects that house the VisualBrush).
Additionally, I should say that I personally would use a Canvas in lieu of the StackPanel, as the Canvas is much better suited for absolute positioning of child elements, hence the reason for your question.
Craig, I truly hope this helps. I (like most people on here) will try to help however I can. Good luck!
Got it.
I set the margin to -(theControl.ActualWidth / 2). All my code shifts everything back by that same amount to compensate.
Then I have an event handler for SizeChanged on the control, where I set this value. If the size of the control changes, the margin is update, and everything focuses on the middle of the control. If you have a specific point within the control that you want to center animation on, then use that point instead of the halfway point described above.

Adding Enumeration Value to Silverlight Attribute/Property

In the <ImageBrush/> element, there are AlignmentX and AlignmentY attributes with values Left/Center/Right and Top/Center/Bottom, respectively.
What I'm wanting to do is set my own value in, for example, AlignmentX either as a value or as another enumeration like AlignmentX="HalfCenter" where HalfLeft equals my own value (halfway between Center and Left). For example, if I have this:
<Rectangle Canvas.Left="0" Stroke="LimeGreen" StrokeThickness="16" Canvas.Top="0"
Width="400" Height="400" >
<Rectangle.Fill>
<ImageBrush ImageSource="newone.jpg"
Stretch="None" AlignmentX="HalfLeft" AlignmentY="Top" />
</Rectangle.Fill>
</Rectangle>
I don't know if this is a Dependency Property, Attached Property or otherwise (don't yet know how to create those). In the helpfile, it says in TileBrush.AlignmentXProperty field: Public Shared ReadOnly AlignmentXProperty As DependencyProperty. Does the ReadOnly word here mean that I can't set this property to a custom property?
If this can't be an override of that property, how can I create my own? I think this is an Attached Property and it could be called something different, like OffsetX and OffsetY that set an ImageBrush to a location inside its parent Shape. I'm getting very confused by the SL documentation on how I would do this though (almost no examples in VB.NET - but even the C# ones aren't all that revealing).
If it is possible, how would I get started on this?
Save yourself the pain and just use a value convertor and even that is going to be a little tricky, since you are going to have to apply a rendertransform or something to react to your enums.
You also could write your own panel which is probably a better idea.
You have a few different problems here to confront, creating the attached property, validating the enum, having the enum do what you want it to do when it is set.
Your also going to have to learn about MeasureOverride and ArrangeOverride
If you just can't help yourself ... Look Here

How to change x,y origin of canvas to bottom left and flip the y coordinates?

I have a bunch of data points that I would like to two-way bind to points on a canvas.
The points assume larger y values are reflected in an upwards direction like most math graphs.
How do I change the x,y origin of the canvas to the bottom left corner and reverse it's interpretation of the y coordinate?
(I would like to stay in XAML)
<Canvas>
<Canvas.LayoutTransform>
<ScaleTransform ScaleX="1" ScaleY="-1" CenterX=".5" CenterY=".5" />
</Canvas.LayoutTransform>
</Canvas>
I tried the ScaleTransform method extensively: It does not work. It only shifts one of the 2 coordinates, never both. This, however, works as advertised:
<Canvas Name="myCanvas" Width="0" Height="0" RenderTransform="1 0 0 -1 0 0"
HorizontalAlignment="Center" VerticalAlignment="Center" >
If you use databinding you can use a TypeConvertor, but for that you have to go outside the XAML and you need to know the size of the canvas beforehand.
I'd probably create a custom panel instead of using Canvas and give it the attached properties that make sense for your needs. Here is an example of implementing a custom panel:
http://blog.boschin.it/articles/silverlight-radialpanel.aspx
Something like Canvas is very simple since you don't have to do much in the measure and arrange overrides.
You may also be able to inherit from Canvas and override ArrangeOverride, I haven't tried that but it may work.

Databind RenderTransform Scaling in Silverlight 2 Beta 2

Anyone know if it's possible to databind the ScaleX and ScaleY of a render transform in Silverlight 2 Beta 2? Binding transforms is possible in WPF - But I'm getting an error when setting up my binding in Silverlight through XAML. Perhaps it's possible to do it through code?
<Image Height="60" HorizontalAlignment="Right"
Margin="0,122,11,0" VerticalAlignment="Top" Width="60"
Source="Images/Fish128x128.png" Stretch="Fill"
RenderTransformOrigin="0.5,0.5" x:Name="fishImage">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="1"/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Image.RenderTransform>
</Image>
I want to bind the ScaleX and ScaleY of the ScaleTransform element.
I'm getting a runtime error when I try to bind against a double property on my data context:
Message="AG_E_PARSER_BAD_PROPERTY_VALUE [Line: 1570 Position: 108]"
My binding looks like this:
<ScaleTransform ScaleX="{Binding Path=SelectedDive.Visibility}"
ScaleY="{Binding Path=SelectedDive.Visibility}"/>
I have triple verified that the binding path is correct - I'm binding a slidebar against the same value and that works just fine...
Visibility is of type double and is a number between 0.0 and 30.0. I have a value converter that scales that number down to 0.5 and 1 - I want to scale the size of the fish depending on the clarity of the water. So I don't think it's a problem with the type I'm binding against...
ScaleTransform doesn't have a data context so most likely the binding is looking for SelectedDive.Visibility off it's self and not finding it. There is much in Silverlight xaml and databinding that is different from WPF...
Anyway to solve this you will want to set up the binding in code**, or manually listen for the PropertyChanged event of your data object and set the Scale in code behind.
I would choose the latter if you wanted to do an animation/storyboard for the scale change.
** i need to check but you may not be able to bind to it. as i recall if the RenderTransform is not part of an animation it gets turned into a matrix transform and all bets are off.
Is it a runtime error or compile-time, Jonas? Looking at the documentation, ScaleX and ScaleY are dependency properties, so you should be able to write
<ScaleTransform ScaleX="{Binding Foo}" ScaleY="{Binding Bar}" />
... where Foo and Bar are of the appropriate type.
Edit: Of course, that's the WPF documentation. I suppose it's possible that they've changed ScaleX and ScaleY to be standard properties rather than dependency properties in Silverlight. I'd love to hear more about the error you're seeing.
Ah I think I see your problem. You're attempting to bind a property of type Visibility (SelectedDive.Visibility) to a property of type Double (ScaleTransform.ScaleX). WPF/Silverlight can't convert between those two types.
What are you trying to accomplish? Maybe I can help you with the XAML. What is "SelectedDive" and what do you want to happen when its Visibility changes?
Sorry - was looking for the answer count to go up so I didn't realise you'd edited the question with more information.
OK, so Visibility is of type Double, so the binding should work in that regard.
As a workaround, could you try binding your ScaleX and ScaleY values directly to the slider control that SelectedDive.Visibility is bound to? Something like:
<ScaleTransform ScaleX="{Binding ElementName=slider1,Path=Value}" ... />
If that works then it'll at least get you going.
Edit: Ah, I just remembered that I read once that Silverlight doesn't support the ElementName syntax in bindings, so that might not work.
Yeah maybe the embedded render transforms aren't inheriting the DataContext from the object they apply to. Can you force the DataContext into them? For example, give the transform a name:
<ScaleTransform x:Name="myScaler" ... />
... and then in your code-behind:
myScaler.DataContext = fishImage.DataContext;
... so that the scaler definitely shares its DataContext with the Image.
Ok, is the Image itself picking up the DataContext properly?
Try adding this:
<Image Tooltip="{Binding SelectedDive.Visibility}" ... />
If that compiles and runs, hover over the image and see if it displays the right value.
I was hoping to solve this through XAML, but turns out Brian's suggestion was the way to go. I used Matt's suggestion to give the scale transform a name, so that I can access it from code. Then I hooked the value changed event of the slider, and manually updates the ScaleX and ScaleY property. I kept my value converter to convert from the visibility range (0-30m) to scale (0.5 to 1). The code looks like this:
private ScaleConverter converter;
public DiveLog()
{
InitializeComponent();
converter = new ScaleConverter();
visibilitySlider.ValueChanged += new
RoutedPropertyChangedEventHandler<double>(visibilitySlider_ValueChanged);
}
private void visibilitySlider_ValueChanged(object sender,
RoutedPropertyChangedEventArgs<double> e)
{
fishScale.ScaleX = (double)converter.Convert(e.NewValue,
typeof(double), null, CultureInfo.CurrentCulture);
fishScale.ScaleY = fishScale.ScaleX;
}

Resources