Strange Windows.Opacity behavior - c#

I have a button event that causes smooth opacity and window minimize.
private void Button_WindowMinimize(object sender, EventArgs e)
{
DoubleAnimation WindowOpacity = new DoubleAnimation()
{
From = Opacity,
To = 0,
Duration = TimeSpan.FromMilliseconds(300)
};
WindowOpacity.Completed += (se, ex) => { Opacity = 1; WindowState = WindowState.Minimized; };
BeginAnimation(Window.OpacityProperty, WindowOpacity);
}
When the window is minimized, I cause a opacity Opacity = 1; (so that I can see a screenshot on the taskbar when mouseover).
Why does the assignment fail Opacity = 1;? The resulting opacity is set to zero. Why is this not working? Thanks

By default animations keep the final value after they are completed. If you want to reset the value after they are completed, you should set FillBehavior to Stop:
DoubleAnimation WindowOpacity = new DoubleAnimation()
{
From = Opacity,
To = 0,
Duration = TimeSpan.FromMilliseconds(300),
FillBehavior = FillBehavior.Stop
};
WindowOpacity.Completed += (se, ex) => { WindowState = WindowState.Minimized; };
BeginAnimation(Window.OpacityProperty, WindowOpacity);

Related

WPF MediaElement Opacity is not set after executing Storyline

I'm using DoubleAnimation and Storyboard to control Opacity of MediaElement. The animation itself works fine, but if I call Disappear and playVid after several seconds, the Opacity of the player remains 0! What's the problem?
public void playVid(string source, bool isMainVid)
{
player.Opacity = 1;
player.Play(); //player.Opacity is 0 here!
}
public void Disappear()
{
DoubleAnimation fadeOut = new DoubleAnimation
{
To = 0,
Duration = new Duration(TimeSpan.FromMilliseconds(1000))
};
fadeOut.Completed += (s, e) =>
{
player.Stop();
};
var storyboard = new Storyboard();
storyboard.Children.Add(fadeOut);
Storyboard.SetTargetName(fadeOut, player.Name);
Storyboard.SetTargetProperty(fadeOut, new PropertyPath(OpacityProperty));
storyboard.Begin(mainGrid, HandoffBehavior.SnapshotAndReplace); //mainGrid is player's parent
}
Use FillBehavior equal to Stop, but also set the Opacity of your player to the final opacity value (in the Completed handler). Otherwise, it will be reset to its value before the animation.
var fadeOut = new DoubleAnimation
{
To = 0,
Duration = new Duration(TimeSpan.FromMilliseconds(1000)),
FillBehavior = FillBehavior.Stop
};
fadeOut.Completed += (s, e) =>
{
player.Stop();
player.Opacity = 0;
};
See this post for other approaches.

Cursor = Cursors.None for popup in code

Im trying to set the cursor to none in code for a popup but I cant get it to work. The cursor is still shown when it is over the popup. What am I doing wrong?
public void SubWindow_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
TextBlock popupText = new TextBlock();
popupText.Text = "Complete" ;
popupText.Background = Brushes.Transparent;
popupText.Foreground = Brushes.White;
popupText.Width = 130;
popupText.FontSize = 30;
popupText.IsHitTestVisible = false;
popupText.Cursor = Cursors.None;
Popup Popup = new Popup();
Popup.AllowsTransparency = true;
Popup.PlacementRectangle = new Rect(1086, 16, 0, 0);
Popup.IsHitTestVisible = false;
Popup.Cursor = Cursors.None;
Popup_Text.Child = popupText;
Popup.IsOpen = true;
}
Don't set the IsHitTestVisible property of the TextBlock to false:
TextBlock popupText = new TextBlock();
popupText.Text = "Complete";
popupText.Background = Brushes.Transparent;
popupText.Foreground = Brushes.White;
popupText.Width = 130;
popupText.Height = 130;
popupText.FontSize = 30;
//popupText.IsHitTestVisible = false;
popupText.Cursor = Cursors.None;
Popup Popup = new Popup();
//Popup.AllowsTransparency = true;
Popup.PlacementRectangle = new Rect(1086, 16, 0, 0);
Popup.IsHitTestVisible = false;
Popup.Cursor = Cursors.None;
Popup.Child = popupText;
Popup.IsOpen = true;
Also note that your app can only change the cursor when the cursor is actually over one of your app's elements. The "background" of a transparent Popup does not belong to your application so Cursors.None will only apply when you move the mouse pointer over the actual text in the TextBlock.

Sticky WPF window

I am trying to create Sticky WPF window.
If window nearer left stick to left or stick right if nearer to right else stick to top
Below the code I am using,
private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.DragMove();
}
private void Window_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
Point currentPoints = PointToScreen(Mouse.GetPosition(this));
//Place left
if (currentPoints.X < (300))
{
DoubleAnimation moveAnimation = new DoubleAnimation(-190, TimeSpan.FromSeconds(1));
_MyWindow.BeginAnimation(Window.LeftProperty, moveAnimation);
}
//Place Right
else if (currentPoints.X > (Screen.PrimaryScreen.WorkingArea.Width - 300))
{
DoubleAnimation moveAnimation = new DoubleAnimation(Screen.PrimaryScreen.WorkingArea.Width + 190, TimeSpan.FromSeconds(1));
_MyWindow.BeginAnimation(Window.LeftProperty, moveAnimation);
}
//Place top
else
{
DoubleAnimation TopAnimation = new DoubleAnimation(-190, TimeSpan.FromSeconds(1));
_MyWindow.BeginAnimation(Window.TopProperty, TopAnimation, HandoffBehavior.Compose);
}
}
The above code moves window only once.
on MSDN, How to: Set a Property After Animating It with a Storyboard
To run animation again, set BeginAnimation Property to NULL,
I tried setting the property to NULL before animation.
And the code now works fine.
Now the code looks like
private void Window_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
Point currentPoints = PointToScreen(Mouse.GetPosition(this));
if (currentPoints.X < (300))
{
if (_MyWindow.HasAnimatedProperties)
_MyWindow.BeginAnimation(Window.LeftProperty, null);
DoubleAnimation moveAnimation = new DoubleAnimation(-190, TimeSpan.FromSeconds(1));
_MyWindow.BeginAnimation(Window.LeftProperty, moveAnimation);
}
else if (currentPoints.X > (Screen.PrimaryScreen.WorkingArea.Width - 300))
{
if (_MyWindow.HasAnimatedProperties)
_MyWindow.BeginAnimation(Window.LeftProperty, null);
DoubleAnimation moveAnimation = new DoubleAnimation(Screen.PrimaryScreen.WorkingArea.Width + 190, TimeSpan.FromSeconds(1));
_MyWindow.BeginAnimation(Window.LeftProperty, moveAnimation);
}
else
{
if (_MyWindow.HasAnimatedProperties)
_MyWindow.BeginAnimation(Window.TopProperty, null);
DoubleAnimation TopAnimation = new DoubleAnimation(-190, TimeSpan.FromSeconds(1));
_MyWindow.BeginAnimation(Window.TopProperty, TopAnimation, HandoffBehavior.Compose);
}
}
If Noticed, I am placing window at -190 position at left and top to hide some of its part.
But using
Below property, Its resetting the window position to 0.
I dont want it to reset the position
_MyWindow.BeginAnimation(Window.LeftProperty, null);
Can anybody suggest how to do multiple animation without resetting existing position?
Ashish Sapkale
I think your idea of setting LeftProperty to null is right but you should be doing that after the animation is finished.
So add a delegate to your animation and set the property to null in that and see if it works.
example
TopAnimation.Completed += (s,e) =>
{
_MyWindow.BeginAnimation(Window.TopProperty, null);
};
Your other options are to use ThicknessAnimation or TranslateTransform to move your window. Let me know if you are still having problems

Resizing animation on SizeChanged event doesn't work as it should

I want a resizing animation when stackpanel visibility is set to visible state, but instead of that, I'm getting neverending flickering of border containing stackpanel.I don't think I'm doing it wrong.
Stack panel contains an instance of TextBlock.
private void MyBorder_SizeChanged_1(object sender, SizeChangedEventArgs e)
{
if (!first)
{
DoubleAnimation anim = new DoubleAnimation();
anim.From = e.PreviousSize.Height;
anim.To = e.NewSize.Height;
anim.Duration = new Duration(TimeSpan.FromSeconds(1));
Storyboard.SetTarget(anim, MyBorder);
Storyboard.SetTargetProperty(anim, new PropertyPath(Border.HeightProperty));
Storyboard st = new Storyboard();
st.Children.Add(anim);
st.Begin();
}
first = false;
}
private void MyBorder_Tap_1(object sender, GestureEventArgs e)
{
if (MyPanel.Visibility == Visibility.Collapsed)
MyPanel.Visibility = Visibility.Visible;
else
MyPanel.Visibility = Visibility.Collapsed;
}
The problem is that when you animate the height of the border it will trigger the SizeChanged event so you have a loop: size changed event>animate height>size changed event> ..
Also when the sized changed event is fired, the size change has already taken placed so even if that was working you will get a little flicking when it go back to do the animation.
Finally using HEight in an animation force a rendering update so that is not hardware accelerated.
Probably the best would be to either do a Translate Transform or a Scale Transform.
For exemple you could do a scale transform between 0 and 1 directly on MyPanel in the tap event.
This might help you to. It is a work around
private void MyBorder_SizeChanged_1(object sender, SizeChangedEventArgs e)
{
if (!first)
{
DoubleAnimation anim = new DoubleAnimation();
anim.From = e.PreviousSize.Height;
anim.To = e.NewSize.Height;
anim.Duration = new Duration(TimeSpan.FromSeconds(1));
Storyboard.SetTarget(anim, MyBorder);
Storyboard.SetTargetProperty(anim, new PropertyPath(Border.HeightProperty));
Storyboard st = new Storyboard();
st.Children.Add(anim);
st.Completed += st_Completed;
MyBorder.SizeChanged -= MyBorder_SizeChanged_1;
st.Begin();
}
first = false;
}
void st_Completed(object sender, EventArgs e)
{
MyBorder.SizeChanged += MyBorder_SizeChanged_1;
}
private void MyBorder_Tap_1(object sender, GestureEventArgs e)
{
if (MyPanel.Visibility == Visibility.Collapsed)
MyPanel.Visibility = Visibility.Visible;
else
MyPanel.Visibility = Visibility.Collapsed;
}
With reference to the fact that border is getting resized even in the storyboard its better to remove the event of size changed. Try animating the parent container on chld size changed some thing kind of this
I've solved this problem. Silly my, I thought that Measure method of StackPanel is private, and didn't bother to make sure about it, here's solution code for expanding StackPanel on Click.
private void MyBorder_Tap_1(object sender, GestureEventArgs e)
{
if (MyPanel.Visibility == Visibility.Collapsed)
{
MyPanel.Visibility = Visibility.Visible;
MyPanel.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
DoubleAnimation anim = new DoubleAnimation();
anim.From = MyBorder.ActualHeight;
anim.To = MyBorder.ActualHeight + MyPanel.DesiredSize.Height;
anim.Duration = new Duration(TimeSpan.FromSeconds(0.25));
Storyboard.SetTarget(anim, MyBorder);
Storyboard.SetTargetProperty(anim, new PropertyPath(Border.HeightProperty));
Storyboard st = new Storyboard();
st.Children.Add(anim);
st.Begin();
}
else
{
MyPanel.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
DoubleAnimation anim = new DoubleAnimation();
anim.From = MyBorder.ActualHeight;
anim.To = MyBorder.ActualHeight - MyPanel.DesiredSize.Height;
anim.Duration = new Duration(TimeSpan.FromSeconds(0.25));
Storyboard.SetTarget(anim, MyBorder);
Storyboard.SetTargetProperty(anim, new PropertyPath(Border.HeightProperty));
Storyboard st = new Storyboard();
st.Children.Add(anim);
st.Completed += (a,b) => { MyPanel.Visibility = Visibility.Collapsed; };
st.Begin();
}
}

Cannot set Opacity property on ScatterViewItem after an animation has been performed

I am currently removing an element from the user interface by fading it out. This works as expected.
public void HideShape()
{
if (this.TangibleShape != null)
{
DoubleAnimation animation = new DoubleAnimation();
animation.From = 1.0;
animation.To = 0.0;
animation.AutoReverse = false;
animation.Duration = TimeSpan.FromSeconds(1.5);
Storyboard s = new Storyboard();
s.Children.Add(animation);
Storyboard.SetTarget(animation, this.TangibleShape.Shape);
Storyboard.SetTargetProperty(animation, new PropertyPath(ScatterViewItem.OpacityProperty));
s.Begin(this.TangibleShape.Shape);
s.Completed += delegate(object sender, EventArgs e)
{
// call UIElementManager to finally hide the element
UIElementManager.GetInstance().Hide(this.TangibleShape);
};
}
}
The problem is that I want to set the opacity to 1 again in some cases but the TangibleShape.Shape (it's a ScatterViewItem) ignores the command. If I fade out again, the element becomes visible and immediately starts fading out. I don't know how to fix this problem. Does anyone have a hint for me?
public void HideShape()
{
if (this.TangibleShape != null)
{
DoubleAnimation animation = new DoubleAnimation();
animation.From = 1.0;
animation.To = 0.0;
animation.AutoReverse = false;
animation.Duration = TimeSpan.FromSeconds(1.5);
animation.FillBehavior = FillBehavior.Stop; // needed
Storyboard s = new Storyboard();
s.Children.Add(animation);
Storyboard.SetTarget(animation, this.TangibleShape.Shape);
Storyboard.SetTargetProperty(animation, new PropertyPath(ScatterViewItem.OpacityProperty));
s.Completed += delegate(object sender, EventArgs e)
{
// call UIElementManager to finally hide the element
UIElementManager.GetInstance().Hide(this.TangibleShape);
this.TangibleShape.Shape.Opacity = 0.0; // otherwise Opacity will be reset to 1
};
s.Begin(this.TangibleShape.Shape); // moved to the end
}
}
Answer found here: http://social.msdn.microsoft.com/Forums/en-US/7d33ca82-2c02-4004-8b37-47edf4cca34e/scatterviewitem-and-

Categories