I'm creating a custom Silverlight control for Silverlight (specifically wp7). My control is mostly a button ,and when someone taps the button , I want to animate a tall rectangle filled with other contents that flys out from behind the button.
The issue is I do not know how to hide or only draw parts of this rectangle as I comes out. For example, when this rectangle is half way out,only the top half is showing while the rest is hidden. How can I do this without having to write some complex code? Presumably I just need to be able to define some sort of 'view' where only things inside this view are rendered to the screen.
Thoughts? Any help is appreciated!
You can use VisualStateManager to define possible visual states for your view. In addition, you can define transitions between those states (incuding animations). In your button's Click event handler you'd need to tell the VisualStateManager to transit to a different state - and you're done.
http://msdn.microsoft.com/en-us/library/system.windows.visualstatemanager.gotostate%28v=vs.95%29.aspx
This would probably look like this in your view's code behind :
void OnClick(object sender, RoutedEventArgs e)
{
VisualStateManager.GoToState(this, "StateName", true);
}
In order to easily define the animations, you can use Expression Blend 4
In order to ensure that only the parts of the animating rectangle that are within the parent container are shown and nothing outside of that, you need to be able to clip the parent's children to it's bounds. Unfortunately, there is no ClipToBounds property in Silverlight, but you can use Colin Eberhardt's clipping attached behavior to achieve the same effect.
Related
A while I go, I made a demo application with Expression Blend.
My first screen is a big selections of Buttons, so when user click on any of button, it goes to the MainView.
Then in the MainView, I have a list of Menu items that user can click and shows up its corresponing DisplayView. (Appointment Menu Item will shows up AppointmentView etc).
Everything is good, I can click the MenuItem, the Views shows up with animation and transition effects.
But the thing is, with creating in Expression Blend, the MainView, Menu, AppointmentView etc every thing is predefined in the XAML. So when user load the first screen has to load everything into memory.
Now thinking of it, shouldn't the MainView etc be dynamically add into the screen?
How do I do it with Expression Blend? Or the only way to do is just....do it in code-behind myself (writting StoryBoard etc for the dynamic add/remove controls?)
If there is any example/tutorial of doing it, it will be great.
I guess you have very limited possibilities to conditionally load or unload controls exclusively in Blend without writing code-behind.
In general an opening tag in XAML is equivalent to a parameter-less constructor of some class object. As soon as you write the tags your are instantiating an object but that doesn't mean that it's visual appearance is loaded into memory. This only happens when the control is actually shown on the screen.
In my opinion the leanest way to control the appearance of some control is to use a single-child control. Take a Border control for example and add the user control you want to conditionally load to its child property, so you can decide for example whether to load or unload a control.
But unfortunately I think you have to do this in code as well. Take this easy code snippet:
// either instantiate in code or use from markuup
Border myBorder = new Border();
// the control you want to conditionally appear and disappear
UserControl myUserControl = new UserControl();
myBorder.Child.Add(myUserControl);
Of course a much more sophisticated approach is to use Grids. Here you have to use attached properties to add or remove child elements:
// either instantiate in code or use from markuup
Grid myGrid = new Grid();
// the control you want to conditionally appear and disappear
UserControl myUserControl = new UserControl();
// set the target position inside the Grid via the Grids attached properties
Grid.setRow(myUserControl, 1);
Grid.setColumn(myUserControl, 0);
// actually add the control
Grid.Children.Add(myUserControl);
Although I am pretty sure you were aware of all of that I am hoping it helped a bit :)
I have a control template defined, call it myVal, that is used for validation - this is then used for example in a Style targeting textbox where its Validation.ErrorTemplate is set as
Now say there are a number of such textboxes that sit in a view and that this slides in using TranslateTransform and BeginAnimation.
The result is that the adorner used in the ErrorTemplate doesn't follow the position of the textboxes as the view transitions - instead these stay in the starting position. However, the adorners reposition themselves correctly in relation to the textboxes as soon as I set focus or events such as mouse move.
How can I get the adorners to show in the correct position after the transformation without having to change the focus? Is there a way of delaying the validation until after the transition...or how can I "revalidate" the properties once the animation has finished? I read somewhere about calling invalidatevisual but can't see how I'd do that. Any help is much appreciated.
Cheers
Two ideas:
Try adding an AdornerDecorator around the textbox, or around the group of textboxes. This will tell WPF to add another layer for rending adorners. Adding a layer "closer" to the textboxes might help.
If you want to tell the adorner layer to re-render itself, then you can use something like the following code:
var al = AdornerLayer.GetAdornerLayer(myTextBox);
al.Update();
I would like to have a form which has a few controls as transparent overlays over a bitmap. This bitmap is subject to transform matrix (zoom & scroll). I'm trying to achieve a look similar to GoogleMaps where the controls do not move when the background image is panned/zoomed.
I've tried to mimic this in my OnPaint. However, when the window is scrolled only the newly exposed area gets invalidated so my control doesn’t repaint.
I've tried to calculate where the old control was, invalidate that area, and also invalidate the area where it's supposed to have been. When I do this it flickers and you can still see the image as its scrolled.
I tried to put a ButtonControl on my display window. However, it always scrolls with its parent control. I tried to capture the scroll events and then adjust the position of the ButtonControl. This also has a delay update effect so it looks not so good.
Any ideas would be greatly appreciated.
It sounds to me like you need to Invalidate() your control wich handles the OnPaint event.
Unfortunately, you get the flicker because the Auto-scrolling mechanism sets its position, and then you restore it. The result is two messages being sent to the button.
Place your bitmap and scroll logic in a separate control that fill the entire form. That means both your bitmap control and the button are child controls of the form.
Alternatively, draw the button yourself. You will then of course need to do some work on getting it to respond to mouse clicks etc. The ControlPaint class has methods that help you mimic the appearance of Windows controls.
I am using a third party charting library (Infragistics xamChart). I am not satisfied with how tooltips are displayed on a line charts datapoints so I was thinking of using an adorner to make a better looking/interactive tooltip.
What I want to do is have the adorner popup whenever one of the datapoints is hovered over. Does anyone have any pointers on how I can do this? Most of the adorner samples I found are pretty simple ones that just alter the entire control they are adorning.
My main questions are:
Is it possible for an adorner to
appear only when certain elements are
hovered over (and have it appear at
the current cursor position)?
Does anyone have a simple sample they
can share?
Are adorners the right way to go
here? I think the only other option
was to use the popup control but I
though adorners were a nicer
solution.
Thank you.
Perhaps Attached Behaviours could help you? From this article:
The idea is that you set an attached
property on an element so that you can
gain access to the element from the
class that exposes the attached
property. Once that class has access
to the element, it can hook events on
it.
That way you could attach a listener to the MouseEnter event and display your custom ToolTip from there.
I have a small WPF application, which has a Canvas and a Grid. I placed some custom user controls on the Grid. Now I would like to capture some mouse events on them. As a consequence of one event I would like to add (or modify) something to the canvas. However in the user control, you don't have a reference to the underlying canvas. First question, is there a way to get this reference, for example like getElementById(..) in JavaScript.
Also I know that you should avoid such references, if you want a clean architecture. In this case, whats a good practice to catch events at a specific user control and then to be able to invoke something on another object.
You do have access to the Canvas, Grid or any other element in your UserControl. The easiest way yo access them is to make sure each one has a name which is done by using the x:Name attribute.
<Grid x:Name="myGrid">
Then within your UserControl you can access it with myGrid. To access a Grid from outside the UserControl you would need to create a method in your UserControl that allowed you to manipulate it.
There is a this.FindName method you can use in a UserControl which is the equivalent of javascript's getElementById but you shouldn't need to use it given you can access objects directly with their name.
WPF has a new event architecture that may help you out here. So called "routed" events may either "tunnel" from the logical root container, through all intermediate containers, to the event source element, or "bubble" from the source element up (i.e. "tunneling" and "bubbling" events propagate in opposite directions).
All that to say that you can typically intercept events from child elements by registering an event handler at the container. Here's an example of intercepting button click events from buttons in a StackPanel:
<StackPanel ButtonBase.Click="HandleButtonClick">
<Button>Foo</Button>
<Button>Bar</Button>
</StackPanel>
And HandleButtonClick might be implemented like this:
private void HandleButtonClick(object sender, RoutedEventArgs e)
{
var button = e.OriginalSource as Button;
if (button != null) MessageBox.Show(button.Content.ToString());
}
Depending on what sort of "custom controls" you are using, this may not be possible. This is because not all events are "routed" events. WPF control events are usually routed events.