C#教程

关注公众号 jb51net

关闭
首页 > 软件编程 > C#教程 > WPF导航

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

作者: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导航的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文