• 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.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.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
https://www.neowin.net/forum/topic/1053135-wpfc-opacity-animation/
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?

  • 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.

This topic is now closed to further replies.
  • Posts

    • I don't expect to see 12 this year, but not for this reason. Windows 10 got a 21H2 update the year Windows 11 came out, it even got 22H2 the next yet.
    • Android 16 adds a new "network notification" setting that warns you when a rogue "stingray" device is trying to spy on you There are many simple things you can do to keep your private information safe, like using strong passwords, scrutinizing app permissions, and only installing apps from trusted sources. However, some attacks are much harder to protect yourself against, as they’re so sophisticated and stealthy that they can happen without you ever noticing. One such attack tricks your phone into connecting to a fake, insecure mobile network, which is difficult for the average person to detect. Fortunately, the new Android 16 update has a feature that can warn you when someone is using this tactic to snoop on you. This type of attack uses a device called a “stingray.” An attacker sets up this device near a target they want to surveil, and it mimics a legitimate cell tower. The stingray tricks nearby mobile devices into connecting to it, allowing the attacker to collect unique identifiers (like the IMEI) and even force them onto an older, more insecure communication protocol. These identifiers allow attackers to target specific devices for analysis, while switching protocols can let them intercept unencrypted text messages and phone calls. https://www.androidauthority.com/android-16-mobile-network-security-3571497/
    • It's worse in Canary this week. When you type something in the address bar and press enter, most cases it defaults to "Ask copilot" that shoves whatever you wrote into copilot. Then you have to retype whatever you wanted and use the down arrow or mouse to select your search engine instead of copilot. Each version that has this behavior(that can't be turned off in settings yet) I'm sending feedback in hoping they don't do this into other channels.
    • Oh wow i really didn't know about this! 😳 Could you tell where they're available even if not public?
  • Recent Achievements

    • Week One Done
      emptyother earned a badge
      Week One Done
    • Week One Done
      DarkWun earned a badge
      Week One Done
    • Very Popular
      valkyr09 earned a badge
      Very Popular
    • Week One Done
      suprememobiles earned a badge
      Week One Done
    • Week One Done
      Marites earned a badge
      Week One Done
  • Popular Contributors

    1. 1
      +primortal
      567
    2. 2
      ATLien_0
      178
    3. 3
      +FloatingFatMan
      178
    4. 4
      Xenon
      120
    5. 5
      Som
      112
  • Tell a friend

    Love Neowin? Tell a friend!