In a C# Windows Forms app, I have a Form with a Panel with a PictureBox on it. The PictureBox is twice as wide as the Panel and has a graphics drawing in it. On scaling etc. I set AutoScrollPosition to keep the section of interest in the middle of the Panel: no problem. My problem is: when the app starts I want the Panel to show a section in the middle of the drawing, rather than the left hand side.
In the Form constructor I have:
panel1.AutoScroll = true;
panel1.AutoScrollPosition = new Point(100, 0);
textBox1.Text = panel1.AutoScrollPosition.ToString();
But on starting the app, the TextBox shows (0, 0) and the initial scroll position is at the left.
So, for test, I added a button which when pressed also executes:
panel1.AutoScrollPosition = new Point(100, 0);
textBox1.Text = panel1.AutoScrollPosition.ToString();
The TextBox then shows (100, 0) and the panel is scrolled as expected.
I makes no difference whether or not the AutoScrollPosition line is included in the constructor.
What must I do to initialise the scroll position without user interaction?
Finally solved it: you override OnLoad and set AutoScrollPosition in that, e.g.:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
int yScroll = yToCentre - panel1.Height / 2;
panel1.AutoScrollPosition = new Point(0, yScroll);
}
Related
I have a JSlider and I am setting JLabels (that display an icon) as the labels on the JSlider. The JLabels just display an icon. I have a MouseListener attached to the JLabel to listen to the Mouse Click event on the JLabel. However the listener never gets called. I have read about setting the Z-order etc but I am not sure how to set that on the labels of a JSlider. I am trying to make the slider move to the exact location of the label when user clicks on the label. I do not want to display any ticks.
slider = new JSlider(0, 1000, 0);
Hashtable< Integer, JLabel > markers = new Hashtable< Integer, JLabel >();
MyMarker mark300 = new MyMarker(300);
mark300.addMouseListener(MyListener);
MyMarker mark575 = new MyMarker(575);
mark575.addMouseListener(MyListener);
MyMarker mark820 = new MyMarker(820);
mark820.addMouseListener(MyListener);
markers.put(300, mark300);
markers.put(550, mark575);
markers.put(820, mark820);
slider.setLabelTable(markers);
Mouse Clicked Event never reaches MyListener. It appears that the slider captures all the events.
I need a MenuBar on the left side of my screen that can slide in and out. As this app is crossplattform it should be on the left side and not like the usual ApplicationBar on the Bottom or NavigationBar on Top.
What I have so far is:
private bool isTapped = false;
private void TEST_TAP(object sender, TappedRoutedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("TAP");
Storyboard s = new Storyboard();
DoubleAnimation doubleAni = new DoubleAnimation();
doubleAni.To = -30;
if (isTapped) doubleAni.To = 0;
doubleAni.Duration = new Duration(TimeSpan.FromMilliseconds(500));
Storyboard.SetTarget(doubleAni, LOGO);
Storyboard.SetTargetProperty(doubleAni, "(UIElement.RenderTransform).(TranslateTransform.XProperty)");
s.Children.Add(doubleAni);
s.Begin();
}
The bar I want to move is a Grid or should be something similar. But this even fails to move a single Image. I googled a bit and replaced "(UIElement.RenderTransform).(TranslateTransform.XProperty)" with "(Canvas.Left)". This doesn't crash but also doesn't move anything else.
Any ideas or solutions?
EDIT:
Well I played around a lot and now I know (and tested it) that "(Canvas.Left)" only works inside of a Canvas. Yay.
My App looks like this: Scrollview (horizontal) and inside is a Grid with columns to display different stuff. The left-most Column contains another Grid that I want to move out of the screen and back in again. But how do I move a grid with Storyboard-animation?
If anybody thinks of a different way to do this, I'm totally happy if it works in any way.
EDIT2:
It seems to be THE way to use Storyboard.SetTargetProperty(doubleAni, "(UIElement.RenderTransform).(CompositeTransform.TranslateX)"); but it keeps crashing =/
Before using this transform you need to add it:
Storyboard s = new Storyboard();
DoubleAnimation doubleAni = new DoubleAnimation();
doubleAni.To = to;
doubleAni.From = from;
doubleAni.Duration = new Duration(TimeSpan.FromMilliseconds(250));
// THIS LINE IS NEW
NaviBar.RenderTransform = new CompositeTransform();
Storyboard.SetTarget(doubleAni, NaviBar);
Storyboard.SetTargetProperty(doubleAni, "(UIElement.RenderTransform).(CompositeTransform.TranslateX)");
s.Children.Add(doubleAni);
s.Begin();
This does the trick. It's still not the functionality that I wanted but the hardest part - the animation - works now.
I have created a Slider Control and an Edit Control that are linked, so that moving the slider changes the edit box's text, and manually editing the text moves the slider. For the most part it works but after I release the mouse button when dragging the Slider, the Edit Control shows 0. While I'm dragging it does show the correct value.
I can partially fix the problem by adding an if(nPos != 0) clause, which stops that happening. However when I click to move the Slider rather than drag, the Edit Control doesn't update.
Do I need a different handler for when the Slider is clicked rather than dragged? Or am I doing something wrong?
// Updates slider when value is changed in the Edit Box
void CProject1Dlg::OnChangeEdit1() {
SLIDER_1.SetPos(GetDlgItemInt(IDC_EDIT1) / 1000);
}
// Slider horizontal scroll handler
void CProject1Dlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if (nPos != 0) {
SetDlgItemInt(IDC_EDIT1, nPos * 1000);
}
CDialogEx::OnHScroll(nSBCode, nPos, pScrollBar);
}
What happens if you try extracting the position of the slider directly with GetPos rather than using the nPos parameter?
I am using the windows phone emulator. I wrote a very simple program: draw a marker on the map when the user tap the map once.
Then I used map_tap event, and get the tapped location as follows,
private void map_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
Point p = e.GetPosition(null);
GeoCoordinate s = map.ConvertViewportPointToGeoCoordinate(p);
Ellipse myCircle = new Ellipse();
myCircle.Fill = new SolidColorBrush(Colors.Blue);
myCircle.Height = 20;
myCircle.Width = 20;
myCircle.Opacity = 50;
MapOverlay myLocationOverlay = new MapOverlay();
myLocationOverlay.Content = myCircle;
myLocationOverlay.PositionOrigin = new Point(0, 0);
myLocationOverlay.GeoCoordinate = s;
MapLayer myLocationLayer = new MapLayer();
myLocationLayer.Add(myLocationOverlay);
map.Layers.Add(myLocationLayer);
}
The problem is that, the point I get is not the point where the mouse (in the emulator it is a mouse but not a finger) clicked. It is some distance lower (about 50 pixels lower) than where I clicked.
So wherever I click in the emulator, the circle is drawn below where I clicked, it's some kind of weird.
Is there anything wrong with my code?
Thank you very much.
The GestureEventArgs.GetPosition() method takes a parameter specifying what UIElement to get the coordinate relative to (see the MSDN documentation). So, try doing
Point p = e.GetPosition(map);
instead.
I am trying to create an animation to make it look like a button turns over and the back shows. So what I was trying to do is:
1- Show a button with BackgroundColor x. (The button now has a Width of null, the property ActualWidth does have a value.)
2- Create a double animation that changes the width of the button to zero.
DoubleAnimation widthAnimation = new DoubleAnimation();
widthAnimation.From = this.ActualWidth;
widthAnimation.To = 0;
widthAnimation.SpeedRatio = 3;
widthAnimation.Duration = TimeSpan.FromMilliseconds(800);
3- Change the BackgroundColor of the button.
ColorAnimation colorAnimation = new ColorAnimation();
colorAnimation.From = State ? _xColor : _yColor;
colorAnimation.To = State ? _yColor : _xColor;
colorAnimation.BeginTime = TimeSpan.FromMilliseconds(400);
colorAnimation.Duration = TimeSpan.Zero;
4- Change the width back to it's original value.
widthAnimation.AutoReverse = true;
The problem is when the animation runs twice the animation reads this.ActualWidth while animating, which causes it to fail to the original width. How can I solve this? I would like to set the Width back to null again, but it seems impossible to me.
You'd better use xaml style and template to "declare" what you want and let WPF/Silverlight take care of all.
If you try to do the same thing by code you can do it but you need to know what the framework does behind the scenes.
Basically you can set
- Style to define the values of some properties of the control
- DataTemplate to define the visual representation of the control's content
- ControlTemplate to define the appearance of the control
Each of those can have Triggers
- Property Triggers
to set properties or starts actions, such as an animation
when a property value changes or when an event is raised;
EventTriggers and Storyboards
to start a set of actions based on the occurrence of an event
If you like to learn about XAML Style and Template,
take a look at http://msdn.microsoft.com/en-us/library/ms745683.aspx
Spend a day to learn and save many hours (or days) of try and error and frustration!
To go right to the point, in your case I think you should use a Storyboard.
See http://msdn.microsoft.com/en-us/library/ms742868.aspx
where you can find also the code equivalent of XAML examples
I came to the idea to targetting the MaxWidth instead of the actual Width. I now use a KeyFrameCollection which sets the MaxWidth to int.MaxValue at the start (so also at the end when using autoreverse).
It will work fine untill there will be phones with a resolution bigger than the max int value.
The code:
DoubleAnimationUsingKeyFrames widthAnimation = new DoubleAnimationUsingKeyFrames();
widthAnimation.KeyFrames.Add(new DiscreteDoubleKeyFrame()
{
KeyTime = TimeSpan.Zero,
Value = int.MaxValue,
});
widthAnimation.KeyFrames.Add(new LinearDoubleKeyFrame()
{
KeyTime = TimeSpan.FromMilliseconds(1),
Value = ActualWidth,
});
widthAnimation.KeyFrames.Add(new LinearDoubleKeyFrame()
{
KeyTime = TimeSpan.FromMilliseconds(400),
Value = 0,
});
widthAnimation.Duration = TimeSpan.FromMilliseconds(400);
widthAnimation.AutoReverse = true;