基于WPF实现3D导航栏控件

 更新时间:2024年03月26日 10:00:31   作者:WPF开发者  
这篇文章主要介绍了如何基于WPF实现简单的3D导航栏控件效果,文中的示例代码讲解详细,对我们的学习或工作有一定帮助,需要的小伙伴可以参考一下

WPF实现3D导航

框架支持.NET4 至 .NET8

Visual Studio 2022;

AnimationNavigationBar3D 带有 3D 效果的导航栏控件的样式。包含多个 AnimationNavigationBar3DItem ,通过 UniformGrid 进行排列,超出显示区域的项可以滚动查看。

AnimationNavigationBar3DItem 继承 ListBboxItem 是 3D 导航栏中的每个项。使用 Viewport3D 来创建一个具有 3D 效果的容器,当鼠标移入或移出时,旋转动画来改变项的外观。它包含一个正面 Background 和一个背面 ContentBack ,可以显示不同的内容。使用可以根据需要自定义内容,如果在每个项中只设置了正面内容而没有设置背面内容,那么背面会自动克隆 GetXmlReader 并显示与正面相同的内容。

GetXmlReader 用于通过将 UIElement 对象转换为 XML 字符串,再将其转换回 UIElement 对象,实现对 UIElement 对象的克隆。

实现代码

1)新增 AnimationNavigationBar3D.cs 代码如下:

    public class AnimationNavigationBar3D : ListBox
    {
        static AnimationNavigationBar3D()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(AnimationNavigationBar3D),
                new FrameworkPropertyMetadata(typeof(AnimationNavigationBar3D)));
        }
        protected override bool IsItemItsOwnContainerOverride(object item)
        {
            return item is AnimationNavigationBar3DItem;
        }
        protected override DependencyObject GetContainerForItemOverride()
        {
            return new AnimationNavigationBar3DItem();
        }
    }

2)新增 AnimationNavigationBar3DItem.cs 代码如下:

    public class AnimationNavigationBar3DItem : ListBoxItem
    {
        public static readonly DependencyProperty FillProperty =
            DependencyProperty.Register("Fill", typeof(Brush), typeof(AnimationNavigationBar3DItem),
                new PropertyMetadata(null));

        public static readonly DependencyProperty ContentBackProperty =
            DependencyProperty.Register("ContentBack", typeof(object), typeof(AnimationNavigationBar3DItem),
                new PropertyMetadata(null));

        static AnimationNavigationBar3DItem()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(AnimationNavigationBar3DItem),
                new FrameworkPropertyMetadata(typeof(AnimationNavigationBar3DItem)));
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            if (ContentBack == null) 
                ContentBack = ControlsHelper.GetXmlReader(Content);
        }

        /// <summary>
        ///  Color fore
        /// </summary>
        public Brush Fill
        {
            get => (Brush)GetValue(FillProperty);
            set => SetValue(FillProperty, value);
        }

        /// <summary>
        ///  The content after the mouse is moved in
        /// </summary>
        public object ContentBack
        {
            get => (object)GetValue(ContentBackProperty);
            set => SetValue(ContentBackProperty, value);
        }
    }

3)新增 AnimationNavigationBar3D.xaml 代码如下:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:controls="clr-namespace:WPFDevelopers.Controls">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="Basic/ControlBasic.xaml" />
        <ResourceDictionary Source="Basic/Animations.xaml" />
    </ResourceDictionary.MergedDictionaries>
    <Style
        x:Key="WD.AnimationNavigationBar3DItem"
        BasedOn="{StaticResource WD.ControlBasicStyle}"
        TargetType="{x:Type controls:AnimationNavigationBar3DItem}">
        <Setter Property="Width" Value="80" />
        <Setter Property="Height" Value="80" />
        <Setter Property="HorizontalContentAlignment" Value="Center" />
        <Setter Property="VerticalContentAlignment" Value="Center" />
        <Setter Property="Foreground" Value="{DynamicResource WD.WindowForegroundColorBrush}" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type controls:AnimationNavigationBar3DItem}">
                    <Viewport3D Width="{TemplateBinding Height}" Height="{TemplateBinding Width}">
                        <Viewport3D.Triggers>
                            <EventTrigger RoutedEvent="MouseEnter">
                                <BeginStoryboard>
                                    <Storyboard Storyboard.TargetName="axis3d" Storyboard.TargetProperty="Angle">
                                        <DoubleAnimation
                                            EasingFunction="{StaticResource WD.CubicEaseInOut}"
                                            To="90"
                                            Duration="00:00:1" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </EventTrigger>
                            <EventTrigger RoutedEvent="MouseLeave">
                                <BeginStoryboard>
                                    <Storyboard Storyboard.TargetName="axis3d" Storyboard.TargetProperty="Angle">
                                        <DoubleAnimation
                                            EasingFunction="{StaticResource WD.CubicEaseInOut}"
                                            To="0"
                                            Duration="00:00:1" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </EventTrigger>
                        </Viewport3D.Triggers>
                        <Viewport3D.Camera>
                            <OrthographicCamera
                                LookDirection="0,0,-100"
                                Position="0,0,100"
                                UpDirection="0,1,0" />
                        </Viewport3D.Camera>
                        <Viewport3D.Children>
                            <ModelVisual3D>
                                <ModelVisual3D.Content>
                                    <AmbientLight Color="{DynamicResource WD.BackgroundColor}" />
                                </ModelVisual3D.Content>
                            </ModelVisual3D>
                            <ContainerUIElement3D>
                                <ContainerUIElement3D.Transform>
                                    <RotateTransform3D>
                                        <RotateTransform3D.Rotation>
                                            <AxisAngleRotation3D
                                                x:Name="axis3d"
                                                Angle="0"
                                                Axis="1 0 0" />
                                        </RotateTransform3D.Rotation>
                                    </RotateTransform3D>
                                </ContainerUIElement3D.Transform>
                                <Viewport2DVisual3D>
                                    <Viewport2DVisual3D.Material>
                                        <DiffuseMaterial Viewport2DVisual3D.IsVisualHostMaterial="True" />
                                    </Viewport2DVisual3D.Material>
                                    <Viewport2DVisual3D.Geometry>
                                        <MeshGeometry3D
                                            Positions="-1,1,1    -1,-1,1   1,-1,1    1,1,1"
                                            TextureCoordinates="0,0   0,1     1,1  1,0"
                                            TriangleIndices="0 1 2 0 2 3" />
                                    </Viewport2DVisual3D.Geometry>
                                    <Border
                                        Width="110"
                                        Height="110"
                                        Background="{TemplateBinding Background}"
                                        CornerRadius="0,0,0,0">
                                        <ContentPresenter
                                            x:Name="PART_ContentPresenter"
                                            HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                            VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                            SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                            TextElement.Foreground="{TemplateBinding Foreground}" />
                                    </Border>
                                </Viewport2DVisual3D>
                                <Viewport2DVisual3D>
                                    <Viewport2DVisual3D.Material>
                                        <DiffuseMaterial Viewport2DVisual3D.IsVisualHostMaterial="True" />
                                    </Viewport2DVisual3D.Material>
                                    <Viewport2DVisual3D.Geometry>
                                        <MeshGeometry3D
                                            Positions="-1,1,1  1,1,1   1,1,-1   -1,1,-1"
                                            TextureCoordinates="0,0   0,1   1,1  1,0"
                                            TriangleIndices="0 1 2 0 2 3" />
                                    </Viewport2DVisual3D.Geometry>
                                    <Border
                                        Width="110"
                                        Height="110"
                                        Background="{TemplateBinding Fill}"
                                        CornerRadius="0,0,0,0"
                                        RenderTransformOrigin="0.5,0.5">
                                        <Border.RenderTransform>
                                            <TransformGroup>
                                                <RotateTransform Angle="90" />
                                            </TransformGroup>
                                        </Border.RenderTransform>
                                        <ContentPresenter
                                            HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                            VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                            Content="{Binding ContentBack, RelativeSource={RelativeSource AncestorType={x:Type controls:AnimationNavigationBar3DItem}}}"
                                            SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                            TextElement.Foreground="{TemplateBinding Foreground}" />
                                    </Border>
                                </Viewport2DVisual3D>
                            </ContainerUIElement3D>
                        </Viewport3D.Children>
                    </Viewport3D>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style
        x:Key="WD.AnimationNavigationBar3D"
        BasedOn="{StaticResource WD.ControlBasicStyle}"
        TargetType="{x:Type controls:AnimationNavigationBar3D}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type controls:AnimationNavigationBar3D}">
                    <Border
                        Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                        UseLayoutRounding="{TemplateBinding UseLayoutRounding}">
                        <ScrollViewer VerticalScrollBarVisibility="Auto">
                            <ItemsPresenter />
                        </ScrollViewer>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="ItemsPanel">
            <Setter.Value>
                <ItemsPanelTemplate>
                    <UniformGrid Columns="{Binding Items.Count, RelativeSource={RelativeSource AncestorType={x:Type controls:AnimationNavigationBar3D}}}" />
                </ItemsPanelTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style BasedOn="{StaticResource WD.AnimationNavigationBar3DItem}" TargetType="{x:Type controls:AnimationNavigationBar3DItem}" />
    <Style BasedOn="{StaticResource WD.AnimationNavigationBar3D}" TargetType="{x:Type controls:AnimationNavigationBar3D}" />
</ResourceDictionary>

4)新增 GetXmlReader.cs 代码如下:

 public static object GetXmlReader(object Content)
 {
     var originalContent = Content as UIElement;
     string contentXaml = XamlWriter.Save(originalContent);
     using (StringReader stringReader = new StringReader(contentXaml))
     {
         using (XmlReader xmlReader = XmlReader.Create(stringReader))
         {
             object clonedContent = XamlReader.Load(xmlReader);

             if (clonedContent is UIElement clonedElement)
             {
                 return clonedElement;
             }
         }
     }
     return null;
 }

5)新增 AnimationNavigationBar3D.xaml 示例代码如下:

<wd:AnimationNavigationBar3D VerticalAlignment="Bottom">
    <wd:AnimationNavigationBar3DItem Background="#E21854" Fill="#FD3574">
        <StackPanel VerticalAlignment="Center">
            <Path
                Width="40"
                Height="40"
                Data="{StaticResource WD.SmileyOutlineGeometry}"
                Fill="{DynamicResource WD.WindowForegroundColorBrush}"
                Stretch="Uniform" />
            <TextBlock HorizontalAlignment="Center" Text="Emoji" />
        </StackPanel>
    </wd:AnimationNavigationBar3DItem>
    <wd:AnimationNavigationBar3DItem Background="#41A545" Fill="#5EECA6">
        <StackPanel VerticalAlignment="Center">
            <Path
                Width="40"
                Height="40"
                Data="{StaticResource WD.BusGeometry}"
                Fill="{DynamicResource WD.WindowForegroundColorBrush}"
                Stretch="Uniform" />
            <TextBlock HorizontalAlignment="Center" Text="Bus" />
        </StackPanel>
    </wd:AnimationNavigationBar3DItem>
    <wd:AnimationNavigationBar3DItem Background="#0A58F0" Fill="#3A7DFE">
        <StackPanel VerticalAlignment="Center">
            <Path
                Width="40"
                Height="40"
                Data="{StaticResource WD.FriendGeometry}"
                Fill="{DynamicResource WD.WindowForegroundColorBrush}"
                Stretch="Uniform" />
            <TextBlock HorizontalAlignment="Center" Text="Friend" />
        </StackPanel>
    </wd:AnimationNavigationBar3DItem>
    <wd:AnimationNavigationBar3DItem Background="#5F0574" Fill="#8E1FA4">
        <StackPanel VerticalAlignment="Center">
            <Path
                Width="40"
                Height="40"
                Data="{StaticResource WD.AlarmClockGeometry}"
                Fill="{DynamicResource WD.WindowForegroundColorBrush}"
                Stretch="Uniform" />
            <TextBlock HorizontalAlignment="Center" Text="Clock" />
        </StackPanel>
    </wd:AnimationNavigationBar3DItem>
    <wd:AnimationNavigationBar3DItem Background="#1F0355" Fill="#5B31AD">
        <wd:AnimationNavigationBar3DItem.Content>
            <StackPanel VerticalAlignment="Center">
                <Path
                    Width="40"
                    Height="40"
                    Data="{StaticResource WD.BuildingRegularGeometry}"
                    Fill="{DynamicResource WD.WindowForegroundColorBrush}"
                    Stretch="Uniform" />
                <TextBlock HorizontalAlignment="Center" Text="Regular" />
            </StackPanel>
        </wd:AnimationNavigationBar3DItem.Content>
        <wd:AnimationNavigationBar3DItem.ContentBack>
            <StackPanel VerticalAlignment="Center">
                <Path
                    Width="40"
                    Height="40"
                    Data="{StaticResource WD.BuildingRegularGeometry}"
                    Fill="{DynamicResource WD.WindowForegroundColorBrush}"
                    Stretch="Uniform" />
                <TextBlock HorizontalAlignment="Center" Text="建筑" />
            </StackPanel>
        </wd:AnimationNavigationBar3DItem.ContentBack>
    </wd:AnimationNavigationBar3DItem>
</wd:AnimationNavigationBar3D>

效果图

以上就是基于WPF实现3D导航栏控件的详细内容,更多关于WPF导航的资料请关注脚本之家其它相关文章!

相关文章

  • Unity的Console的控制类LogEntries深入解析与实用案例

    Unity的Console的控制类LogEntries深入解析与实用案例

    这篇文章主要为大家介绍了Unity的Console的控制类LogEntries深入解析与实用案例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • 基于C#实现PDF转HTML并自定义转换选项

    基于C#实现PDF转HTML并自定义转换选项

    在数字化办公场景中,PDF与HTML的互操作需求日益增长,如何在 C# 生态中实现PDF 转 HTML 的高保真转换是开始过程中常见的问题,下面我们就来看看具体实现方法吧
    2025-09-09
  • C#数组的常用操作方法小结

    C#数组的常用操作方法小结

    Array数组在C#中同样是最基本的数据结构,下面为大家C#数组的常用操作方法小结,皆为细小的代码段,欢迎收看收藏
    2016-05-05
  • C#调用SQL语句时乘号的用法

    C#调用SQL语句时乘号的用法

    这篇文章主要介绍了C#调用SQL语句时乘号的用法,可避免因符号引起的程序错误,是C#程序设计人员有必要掌握的,需要的朋友可以参考下
    2014-08-08
  • implicit关键字做自定义类型隐式转换的方法

    implicit关键字做自定义类型隐式转换的方法

    implicit 关键字用于声明隐式的用户定义类型转换运算符。如果转换过程可以确保不会造成数据丢失,则可使用该关键字在用户定义类型和其他类型之间进行隐式转换,这篇文章就给大家详细介绍implicit关键字做自定义类型隐式转换的方法,需要的朋友可以参考下
    2015-08-08
  • 采用C#代码动态设置文件权限

    采用C#代码动态设置文件权限

    在开发中,我们经常会使用IO操作,例如创建,删除文件等操作。在项目中这样的需求也较多,我们也会经常对这些操作进行编码,但是对文件的权限进行设置,这样的操作可能会手动操作,本文介绍一种采用代码动态对文件设置权限的操作。
    2016-12-12
  • WinForm实现鼠标拖动控件跟随效果

    WinForm实现鼠标拖动控件跟随效果

    这篇文章主要为大家详细介绍了WinForm实现鼠标拖动控件跟随效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-03-03
  • C# Console.WriteLine()用法案例详解

    C# Console.WriteLine()用法案例详解

    这篇文章主要介绍了C# Console.WriteLine()用法案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • C#队列Queue用法实例分析

    C#队列Queue用法实例分析

    这篇文章主要介绍了C#队列Queue用法,实例分析了队列的功能、定义及相关使用技巧,需要的朋友可以参考下
    2015-05-05
  • C# 创建单例的多种方式

    C# 创建单例的多种方式

    这篇文章主要介绍了C# 创建单例的多种方式,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下
    2021-03-03

最新评论