• 0

[WPF/C#] Opacity Animation


Question

Hello gang,

I am back again with another WPF question.

I have a MainWindow and within that a collection of UserControls (menus). Last week I was given help on figuring out why the animation to move these controls from the bottom (hidden) to their correct position. (see first picture)

The code for doing this is here (and it works correctly, thanks Johnny)


private static void Translate(FrameworkElement e, int X, int Y, int dX, int dY, TimeSpan duration)
{
try
{
// Create storyboard
var sb = new Storyboard();
// Create TranslateTransform
TranslateTransform tt2 = new TranslateTransform();
e.RegisterName("TT2", tt2);
e.RenderTransform = tt2;
// Create x Animation
DoubleAnimation aniX = new DoubleAnimation
{
From = X,
To = dX,
Duration = new Duration(duration)
};
sb.Children.Add(aniX);
Storyboard.SetTargetName(aniX, "TT2");
Storyboard.SetTargetProperty(aniX, new PropertyPath(TranslateTransform.XProperty));
// Create Y Animation
DoubleAnimation aniY = new DoubleAnimation
{
From = Y,
To = dY,
Duration = new Duration(duration)
};
sb.Children.Add(aniY);
Storyboard.SetTargetName(aniY, "TT2");
Storyboard.SetTargetProperty(aniY, new PropertyPath(TranslateTransform.YProperty));
// Register Storyboard
e.Resources.Add("SB", sb);
sb.Begin();
// Unregister Storyboard (Cleanup)
e.Resources.Remove("SB");
e.UnregisterName("TT2");
}
catch (Exception ex)
{
LogEx objLog = new LogEx();
objLog.LogException(ex);
objLog = null;
}
}
[/CODE]

The next step when the user navigates up is to hide the top menu (via an opacity animation) Here is the code I have created via Johnny's work and some research.

[CODE]
private static void Translate(FrameworkElement e)
{
try
{
TimeSpan duration = new TimeSpan(0, 0, 0, 3, 0);
var sb = new Storyboard();

TranslateTransform tt2 = new TranslateTransform();
e.RegisterName("MenuFade", tt2);
e.RenderTransform = tt2;
DoubleAnimation aniFade = new DoubleAnimation
{
From = 1.0,
To = 0.0,
Duration = new Duration(duration)
};
sb.Children.Add(aniFade);
Storyboard.SetTargetName(aniFade, "MenuFade");
Storyboard.SetTargetProperty(aniFade, new PropertyPath(BediaMenu.BMenu.OpacityProperty));
//storyboard.Begin(e);
e.Resources.Add("SB", sb);
sb.Begin();
// Unregister Storyboard (Cleanup)
e.Resources.Remove("SB");
e.UnregisterName("MenuFade");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
LogEx objLog = new LogEx();
objLog.LogException(ex);
objLog = null;
}
}
[/CODE]

EDIT:

Here is the code that is called when the user navigates up

[CODE]
private void PageUp(Int16 Count)
{
try
{
foreach (UIElement element in this.BediaCanvas.Children)
{
if (element is Grid)
{
Grid grd = element as Grid;
foreach (UIElement mnuElement in grd.Children)
{
if (mnuElement is BediaMenu.BMenu)
{
BediaMenu.BMenu bMenu = mnuElement as BediaMenu.BMenu;
if (bMenu.Name != "Titlebar")
{
Translate(bMenu);
}
}
}
}
}
}
catch (Exception ex)
{
LogEx objLog = new LogEx();
objLog.LogException(ex);
objLog = null;
}
}
[/CODE]

Not only does it not fade out the menus but they all move to the top (see second image)

Any thoughts?

post-45653-0-84259000-1327183542_thumb.p

post-45653-0-26314100-1327183561.png

Link to comment
Share on other sites

2 answers to this question

Recommended Posts

  • 0

A little unrelated to your problem, but this five-indent loop:


foreach (UIElement element in this.BediaCanvas.Children)
{
if (element is Grid)
{
Grid grd = element as Grid;
foreach (UIElement mnuElement in grd.Children)
{
if (mnuElement is BediaMenu.BMenu)
{
BediaMenu.BMenu bMenu = mnuElement as BediaMenu.BMenu;
if (bMenu.Name != "Titlebar")
{
Translate(bMenu);
}
}
}
}
}[/CODE]

can be simplified into this using some LINQ magic:

[CODE]foreach( var menu in this.BediaCanvas.Children.OfType<Grid>().SelectMany( g => g.Children.OfType<BediaMenu.BMenu>() ).Where( b => b.Name != "Titlebar" ) )
{
Translate( menu );
}[/CODE]

Even without LINQ, you are misusing the "is" operator; "as" already does fail-safe casting.

[CODE]Control c = new TextBlock();
// If you want to do something only if c is a TextBlock using c, use as:
TextBlock txt = c as TextBlock;
if( txt != null ) // c is a TextBlock
{

}
else // c is not a TextBlock
{

}

// "c as TextBlock" == "c is TextBlock ? (TextBlock) c : null" but the cast is performed only once.
[/CODE]

Also, do you really need all of these try-catches? Depending on which exception happens, you might not be able to continue anyway. If you want to capture all exceptions, use the AppDomain.CurrentDomain.UnhandledException event :)

Again, I know that's not the solution to your problem, but...I figured it'd help you.

On a more on-topic note: How is that Translate() methods with 6 parameters called?

Link to comment
Share on other sites

  • 0

Aethec,

Thanks for the LINQ info. I have been playing with C# for a number of years (Been a prof VB developer for the past 17... yea yea yea, ANYWAY...) but I never took the time to learn LINQ. Thanks for the incentive.

As for all the exception handling, I've always been a stickler for serious error handling. Again, this could be my "upbringing"

Here is the code that calls the original loading of the menus, which calls the "Translate" method given to me.


private void PageUp()
{
try
{
Point pntBediaMenuPosition;
Int16 iY = 0;
Int16 iMilliseconds = 400;
Int16 iSeconds = 0;
Int32 iTop = Convert.ToInt16(this.Titlebar.ActualHeight + this.MenuSizeMargin + 10);
Int16 iMenuCount = 1;
foreach (UIElement element in this.BediaCanvas.Children)
{
if (element is Grid)
{
Grid grd = element as Grid;
foreach (UIElement mnuElement in grd.Children)
{
if (mnuElement is BediaMenu.BMenu)
{
BediaMenu.BMenu bMenu = mnuElement as BediaMenu.BMenu;
if (bMenu.Name != "Titlebar")
{
TimeSpan ts = new TimeSpan(0, 0, 0, iSeconds, iMilliseconds);
pntBediaMenuPosition = GetControlPosition(bMenu);
iY = Convert.ToInt16(pntBediaMenuPosition.Y);
if (iMenuCount == 1)
{
//TODO: this is only a start point, still need to fade in color icon
bMenu.Height = (this.MenuSize + this.MenuSizeDifference);
Translate(bMenu, iY, iTop, ts);
iTop += (Convert.ToInt32(this.MenuSize) + this.MenuSizeDifference);
}
else
{
Translate(bMenu, iY, iTop, ts);
iTop += (Convert.ToInt32(this.MenuSize) + this.MenuSizeMargin);
}
iMilliseconds += 50;
if (iMilliseconds == 1000)
{
iMilliseconds = 0;
iSeconds += 1;
}
iMenuCount += 1;
if (iMenuCount > maryMenus.Count)
{
break;
}
}
}
}
}
}
}
catch (Exception ex)
{
LogEx objLog = new LogEx();
objLog.LogException(ex);
objLog = null;
}
}
[/CODE]

Thanks for your time and your input.

Link to comment
Share on other sites

This topic is now closed to further replies.