WPF:如何实现一个使其他 2 个按钮可见并带有淡入淡出的按钮

WPF: how to implement a button that make 2 other buttons visible with fading

我想实现特殊按钮,但我什至不知道如何开始。

我希望我的 Button 的内容 属性 是:Play。单击它时,我希望在左侧和右侧弹出另外 2 个 ButtonsSingle PlayParallel Play

您所要做的就是创建 3 个按钮,然后在两侧按钮上放置一个可见性转换器。创建一个 属性 来保存它们是否应该可见,并将可见性转换器绑定到这个 属性。 Play 按钮应在单击时修改此 属性。

我希望这能让您了解如何开始。

经过大量讨论,这里是解决这个问题的结果:

xaml:

<Window x:Class="WpfApplication3.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:my="clr-namespace:WpfApplication3"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <StackPanel Orientation="Horizontal">
        <Button Name="btnSinglePlay" Visibility="Collapsed" my:VisibilityAnimation.IsActive="True">SinglePlay</Button>
        <Button Name="btnPlay" Click="btnPlay_Click">Play</Button>
        <Button Name="btnParallelPlay" Visibility="Collapsed" my:VisibilityAnimation.IsActive="True">ParallelPlay</Button>
    </StackPanel>
</Grid>

C# 设置两侧按钮可见。

private void btnPlay_Click(object sender, RoutedEventArgs e)
        {
            btnSinglePlay.Visibility = Visibility.Visible;
            btnParallelPlay.Visibility = Visibility.Visible;
        }

和允许淡出 in/fade 的 c# 代码。它来自 WPF Fade Animation 所以支持 Anvaka,而不是我。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Animation;

namespace WpfApplication3
{
    public class VisibilityAnimation : DependencyObject
    {
        private const int DURATION_MS = 200;

        private static readonly Hashtable _hookedElements = new Hashtable();

        public static readonly DependencyProperty IsActiveProperty =
          DependencyProperty.RegisterAttached("IsActive",
          typeof(bool),
          typeof(VisibilityAnimation),
          new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnIsActivePropertyChanged)));

        public static bool GetIsActive(UIElement element)
        {
            if (element == null)
            {
                throw new ArgumentNullException("element");
            }

            return (bool)element.GetValue(IsActiveProperty);
        }

        public static void SetIsActive(UIElement element, bool value)
        {
            if (element == null)
            {
                throw new ArgumentNullException("element");
            }
            element.SetValue(IsActiveProperty, value);
        }

        static VisibilityAnimation()
        {
            UIElement.VisibilityProperty.AddOwner(typeof(FrameworkElement),
                                                  new FrameworkPropertyMetadata(Visibility.Visible, new PropertyChangedCallback(VisibilityChanged), CoerceVisibility));
        }

        private static void VisibilityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            // So what? Ignore.
        }

        private static void OnIsActivePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var fe = d as FrameworkElement;
            if (fe == null)
            {
                return;
            }
            if (GetIsActive(fe))
            {
                HookVisibilityChanges(fe);
            }
            else
            {
                UnHookVisibilityChanges(fe);
            }
        }

        private static void UnHookVisibilityChanges(FrameworkElement fe)
        {
            if (_hookedElements.Contains(fe))
            {
                _hookedElements.Remove(fe);
            }
        }

        private static void HookVisibilityChanges(FrameworkElement fe)
        {
            _hookedElements.Add(fe, false);
        }

        private static object CoerceVisibility(DependencyObject d, object baseValue)
        {
            var fe = d as FrameworkElement;
            if (fe == null)
            {
                return baseValue;
            }

            if (CheckAndUpdateAnimationStartedFlag(fe))
            {
                return baseValue;
            }
            // If we get here, it means we have to start fade in or fade out
            // animation. In any case return value of this method will be
            // Visibility.Visible. 

            var visibility = (Visibility)baseValue;

            var da = new DoubleAnimation
            {
                Duration = new Duration(TimeSpan.FromMilliseconds(DURATION_MS))
            };

            da.Completed += (o, e) =>
            {
                // This will trigger value coercion again
                // but CheckAndUpdateAnimationStartedFlag() function will reture true
                // this time, and animation will not be triggered.
                fe.Visibility = visibility;
                // NB: Small problem here. This may and probably will brake 
                // binding to visibility property.
            };

            if (visibility == Visibility.Collapsed || visibility == Visibility.Hidden)
            {
                da.From = 1.0;
                da.To = 0.0;
            }
            else
            {
                da.From = 0.0;
                da.To = 1.0;
            }

            fe.BeginAnimation(UIElement.OpacityProperty, da);
            return Visibility.Visible;
        }

        private static bool CheckAndUpdateAnimationStartedFlag(FrameworkElement fe)
        {
            var hookedElement = _hookedElements.Contains(fe);
            if (!hookedElement)
            {
                return true; // don't need to animate unhooked elements.
            }

            var animationStarted = (bool)_hookedElements[fe];
            _hookedElements[fe] = !animationStarted;

            return animationStarted;
        }
    }
}