WPF Control Flip

岁酱吖の 提交于 2019-11-30 00:30:50

问题


I've got a control that is mainly comprised of an image and a button. I want to display the image meta data on the back of the image and have the control flip horizontally when the button is pressed:

i.e.

Click the "info" button...

Rotate the image 180 degs around the axis...

Show "back" of image with meta data (or whatever really).

Obviously when the red "close" button is clicked, the image rotates around the final 180 degs so that the image is showing again.

I've not done any 3D really in XAML, but I can't see why this would be too complex...


回答1:


It can be done without 3D. ScaleEffect with changing horizontal scale from 1 to -1 has the same visual effect:

<Image RenderTransformOrigin="0.5,0.5">
    <Image.RenderTransform>
        <ScaleTransform ScaleX="-1" />
    </Image.RenderTransform>
</Image>

You can animate ScaleX property to get rotating effect. You should also change it's Viisibility from Visible to Hidden and vice versa. To make image disappearing after rotating 90 degrees. At the same time back panel should become visible.




回答2:


A UserControl which is flippable:

<UserControl x:Class="Test.UserControls.FlipControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Test.UserControls" Name="control">
    <UserControl.Resources>
        <ContentControl x:Key="BackSide" Content="{Binding Source={x:Reference control}, Path=Back}" RenderTransformOrigin="0.5,0.5">
            <ContentControl.RenderTransform>
                <ScaleTransform ScaleX="-1" />
            </ContentControl.RenderTransform>
        </ContentControl>
    </UserControl.Resources>
    <ContentControl RenderTransformOrigin="0.5,0.5">
        <ContentControl.RenderTransform>
            <TransformGroup>
                <ScaleTransform x:Name="transform" ScaleX="1" />
            </TransformGroup>
        </ContentControl.RenderTransform>
        <ContentControl.Style>
            <Style TargetType="{x:Type ContentControl}">
                <Setter Property="Content" Value="{Binding ElementName=control, Path=Front}" />
                <Style.Triggers>
                    <DataTrigger Value="True">
                        <DataTrigger.Binding>
                            <Binding ElementName="transform" Path="ScaleX">
                                <Binding.Converter>
                                    <local:LessThanXToTrueConverter X="0" />
                                </Binding.Converter>
                            </Binding>
                        </DataTrigger.Binding>
                        <DataTrigger.Setters>
                            <Setter Property="Content" Value="{StaticResource BackSide}"/>
                        </DataTrigger.Setters>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ContentControl.Style>
    </ContentControl>
</UserControl>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Windows.Media.Animation;

namespace Test.UserControls
{
    /// <summary>
    /// Interaction logic for FlipControl.xaml
    /// </summary>
    public partial class FlipControl : UserControl, INotifyPropertyChanged
    {
        public static readonly DependencyProperty FrontProperty =
            DependencyProperty.Register("Front", typeof(UIElement), typeof(FlipControl), new UIPropertyMetadata(null));
        public UIElement Front
        {
            get { return (UIElement)GetValue(FrontProperty); }
            set { SetValue(FrontProperty, value); }
        }

        public static readonly DependencyProperty BackProperty =
            DependencyProperty.Register("Back", typeof(UIElement), typeof(FlipControl), new UIPropertyMetadata(null));
        public UIElement Back
        {
            get { return (UIElement)GetValue(BackProperty); }
            set { SetValue(BackProperty, value); }
        }

        public static readonly DependencyProperty FlipDurationProperty =
            DependencyProperty.Register("FlipDuration", typeof(Duration), typeof(FlipControl), new UIPropertyMetadata((Duration)TimeSpan.FromSeconds(0.5)));
        public Duration FlipDuration
        {
            get { return (Duration)GetValue(FlipDurationProperty); }
            set { SetValue(FlipDurationProperty, value); }
        }

        private bool _isFlipped = false;
        public bool IsFlipped
        {
            get { return _isFlipped; }
            private set
            {
                if (value != _isFlipped)
                {
                    _isFlipped = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("IsFlipped"));
                }
            }
        }

        private IEasingFunction EasingFunction = new SineEase() { EasingMode = EasingMode.EaseInOut };

        public FlipControl()
        {
            InitializeComponent();
        }

        public void Flip()
        {
            var animation = new DoubleAnimation()
            {
                Duration = FlipDuration,
                EasingFunction = EasingFunction,
            };
            animation.To = IsFlipped ? 1 : -1;
            transform.BeginAnimation(ScaleTransform.ScaleXProperty, animation);
            IsFlipped = !IsFlipped;
            OnFlipped(new EventArgs());
        }

        public event EventHandler Flipped;

        protected virtual void OnFlipped(EventArgs e)
        {
            if (this.Flipped != null)
            {
                this.Flipped(this, e);
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, e);
            }
        }
    }

    public class LessThanXToTrueConverter : IValueConverter
    {
        public double X { get; set; }

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return (double)value < X;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }
}

Usage example:

<uc:FlipControl x:Name="fc">
    <uc:FlipControl.Front>
        <Image Source="/Images/Default.ico" />
    </uc:FlipControl.Front>
    <uc:FlipControl.Back>
        <Image Source="/Images/Error.ico" />
    </uc:FlipControl.Back>
</uc:FlipControl>
fc.Flip();



回答3:


old post I know, but take a look at http://thriple.codeplex.com/

Josh smith provided a control that did this back in 2009.




回答4:


Have a look at this project.

I am waiting for Silverlight's plane projections coming to WPF.




回答5:


You can use the idea from this blog which shows how to do it in Silverlight. Pretty much same will work in WPF if we use ViewPort3D instead of Projection http://jobijoy.blogspot.com/2009/04/3d-flipper-control-using-silverlight-30.html



来源:https://stackoverflow.com/questions/6228190/wpf-control-flip

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!