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