Avalonia实例实战五:Carousel自动轮播图

文章目录


一、加载图片

将三张Png图片加载到项目中,在访问前,必须将路径添加到资源中,在csproject文件中加入:

xml 复制代码
 <AvaloniaResource Include="Resources\Images\**" />

不使用avares:直接路径访问:

xml 复制代码
 <Image Source="/Resources/Images/A1.png" />
 <Image Source="/Resources/Images/A2.png" />
 <Image Source="/Resources/Images/A3.png" />>

使用avares:访问:

如果资源在其他程序集中,可以采用avares访问,"PIMS"为程序集名称:

xml 复制代码
 <Image Source="avares://PIMS/Resources/Images/A1.png" />

二、使用Carousel控件

官网示例:

xml 复制代码
<Panel>
    <Carousel Name="slides" >
      <Carousel.PageTransition >
        <CompositePageTransition>
          <PageSlide Duration="0:00:01.500" Orientation="Horizontal" />
        </CompositePageTransition>
      </Carousel.PageTransition>
      <Carousel.Items>
        <Image Source="avares://AvaloniaControls/Assets/pipes.jpg" />
        <Image Source="avares://AvaloniaControls/Assets/controls.jpg" />
        <Image Source="avares://AvaloniaControls/Assets/vault.jpg" />
      </Carousel.Items>
    </Carousel>
    <Panel Margin="20">
      <Button Background="White" Click="Previous">&lt;</Button>
      <Button Background="White" Click="Next" 
              HorizontalAlignment="Right">&gt;</Button>
    </Panel>
  </Panel>

CS:

csharp 复制代码
using Avalonia.Controls;
using Avalonia.Interactivity;

namespace AvaloniaControls.Views
{
   public partial class MainWindow : Window
   {
       public MainWindow()
       {
           InitializeComponent();
       }

       public void Next(object source, RoutedEventArgs args)
       {
           slides.Next();
       }

       public void Previous(object source, RoutedEventArgs args) 
       {
           slides.Previous();
       }
   }
}

实现的很简单,没有其他的属性;设置PageSlide滑动样式,左滑右滑。

增加间隔3秒自动滑动

自定义控件:

csharp 复制代码
public class MyCarousel:Carousel
{
	  //是否自动滚动
	   public static readonly StyledProperty<bool> IsAutoScrollProperty =
	       AvaloniaProperty.Register<PIMSCarousel, bool>
	       (
	           nameof(IsAutoScroll),
	           defaultValue: false
	       );
	
	   public bool IsAutoScroll
	   {
	       get => GetValue(IsAutoScrollProperty);
	       set => SetValue(IsAutoScrollProperty, value);
	   }
	
	   //自动滚动时间间隔
	   public static readonly StyledProperty<int> AutoScrolTimeSpanProperty =
	       AvaloniaProperty.Register<PIMSCarousel, int>
	       (
	           nameof(AutoScrolTimeSpan),
	           defaultValue: 3000//3秒
	       );
	
	   public int AutoScrolTimeSpan
	   {
	       get => GetValue(AutoScrolTimeSpanProperty);
	       set => SetValue(AutoScrolTimeSpanProperty, value);
	   }
   }

再增加一个Timer定时器去自动执行即可。

注意:每次自定义控件,必须附带重写样式,因为原有的主题是基于Carousel原生控件的样式,需要覆盖重写。

三、使用自定义用户控件实现带RadioButton的轮播控件

xml 复制代码
<UserControl
    x:Class="PIMS.Controls.PIMSCarousel"
    xmlns="https://github.com/avaloniaui"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Name="root"
    d:DesignHeight="450"
    d:DesignWidth="800"
    mc:Ignorable="d">
    <Grid RowDefinitions="*,Auto">
        <Carousel Name="cl">
            <Carousel.PageTransition>
                <CompositePageTransition>
                    <PageSlide Orientation="Horizontal" Duration="0:00:00.200" />
                </CompositePageTransition>
            </Carousel.PageTransition>
        </Carousel>
        <ListBox
            Name="lb"
            Grid.Row="1"
            HorizontalAlignment="Center"
            Background="Transparent">
            <ListBox.Styles>
                <Style Selector="ListBox">
                    <Setter Property="ItemsPanel">
                        <ItemsPanelTemplate>
                            <VirtualizingStackPanel Orientation="Horizontal" />
                        </ItemsPanelTemplate>
                    </Setter>
                </Style>
                <Style Selector="RadioButton">
                    <Setter Property="Background" Value="{DynamicResource RadioButtonBackground}" />
                    <Setter Property="Foreground" Value="{DynamicResource RadioButtonForeground}" />
                    <Setter Property="BorderBrush" Value="{DynamicResource RadioButtonBorderBrush}" />
                    <Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}" />
                    <Setter Property="Padding" Value="5,0,0,0" />
                    <Setter Property="HorizontalAlignment" Value="Left" />
                    <Setter Property="VerticalAlignment" Value="Center" />
                    <Setter Property="HorizontalContentAlignment" Value="Left" />
                    <Setter Property="VerticalContentAlignment" Value="Center" />
                    <Setter Property="Template">
                        <ControlTemplate TargetType="RadioButton">
                            <Border
                                Name="RootBorder"
                                Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                CornerRadius="{TemplateBinding CornerRadius}">
                                <Grid ColumnDefinitions="20,*">
                                    <Grid Height="32" VerticalAlignment="Top">
                                        <Ellipse
                                            Name="OuterEllipse"
                                            Width="10"
                                            Height="10"
                                            Fill="White"
                                            Stroke="{DynamicResource RadioButtonOuterEllipseStroke}"
                                            StrokeThickness="{DynamicResource RadioButtonBorderThemeThickness}"
                                            UseLayoutRounding="False" />

                                        <Ellipse
                                            Name="CheckOuterEllipse"
                                            Width="10"
                                            Height="10"
                                            Fill="{DynamicResource RadioButtonOuterEllipseCheckedFill}"
                                            Opacity="0"
                                            Stroke="{DynamicResource RadioButtonOuterEllipseCheckedStroke}"
                                            StrokeThickness="{DynamicResource RadioButtonBorderThemeThickness}"
                                            UseLayoutRounding="False" />

                                        <Ellipse
                                            Name="CheckGlyph"
                                            Width="5"
                                            Height="5"
                                            Fill="White"
                                            Opacity="0"
                                            Stroke="{DynamicResource RadioButtonCheckGlyphStroke}"
                                            UseLayoutRounding="False" />
                                    </Grid>

                                    <ContentPresenter
                                        Name="PART_ContentPresenter"
                                        Grid.Column="1"
                                        Margin="{TemplateBinding Padding}"
                                        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                        VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                        Content="{TemplateBinding Content}"
                                        ContentTemplate="{TemplateBinding ContentTemplate}"
                                        Foreground="{TemplateBinding Foreground}"
                                        RecognizesAccessKey="True" />
                                </Grid>
                            </Border>
                        </ControlTemplate>
                    </Setter>

                    <!--  PointerOver State  -->
                    <Style Selector="^:pointerover /template/ ContentPresenter#PART_ContentPresenter">
                        <Setter Property="Foreground" Value="White" />
                    </Style>

                    <Style Selector="^:pointerover /template/ Border#RootBorder">
                        <Setter Property="Background" Value="{DynamicResource RadioButtonBackgroundPointerOver}" />
                        <Setter Property="BorderBrush" Value="{DynamicResource RadioButtonBorderBrushPointerOver}" />
                    </Style>

                    <Style Selector="^:pointerover /template/ Ellipse#OuterEllipse">
                        <Setter Property="Stroke" Value="{DynamicResource RadioButtonOuterEllipseStrokePointerOver}" />
                        <Setter Property="Fill" Value="red" />
                    </Style>

                    <Style Selector="^:pointerover /template/ Ellipse#CheckOuterEllipse">
                        <Setter Property="Stroke" Value="{DynamicResource RadioButtonOuterEllipseCheckedStrokePointerOver}" />
                        <Setter Property="Fill" Value="Green" />
                    </Style>

                    <Style Selector="^:pointerover /template/ Ellipse#CheckGlyph">
                        <Setter Property="Stroke" Value="{DynamicResource RadioButtonCheckGlyphStrokePointerOver}" />
                        <Setter Property="Fill" Value="White" />
                    </Style>


                    <!--  Pressed State  -->
                    <Style Selector="^:pressed /template/ ContentPresenter#PART_ContentPresenter">
                        <Setter Property="Foreground" Value="{DynamicResource RadioButtonForegroundPressed}" />
                    </Style>

                    <Style Selector="^:pressed /template/ Border#RootBorder">
                        <Setter Property="Background" Value="{DynamicResource RadioButtonBackgroundPressed}" />
                        <Setter Property="BorderBrush" Value="{DynamicResource RadioButtonBorderBrushPressed}" />
                    </Style>

                    <Style Selector="^:pressed /template/ Ellipse#OuterEllipse">
                        <Setter Property="Stroke" Value="{DynamicResource RadioButtonOuterEllipseStrokePressed}" />
                        <Setter Property="Fill" Value="{DynamicResource RadioButtonOuterEllipseFillPressed}" />
                    </Style>

                    <Style Selector="^:pressed /template/ Ellipse#CheckOuterEllipse">
                        <Setter Property="Stroke" Value="{DynamicResource RadioButtonOuterEllipseCheckedStrokePressed}" />
                        <Setter Property="Fill" Value="{DynamicResource RadioButtonOuterEllipseCheckedFillPressed}" />
                    </Style>

                    <Style Selector="^:pressed /template/ Ellipse#CheckGlyph">
                        <Setter Property="Stroke" Value="{DynamicResource RadioButtonCheckGlyphStrokePressed}" />
                        <Setter Property="Fill" Value="{DynamicResource RadioButtonCheckGlyphFillPressed}" />
                    </Style>


                    <!--  Disabled State  -->
                    <Style Selector="^:disabled /template/ ContentPresenter#PART_ContentPresenter">
                        <Setter Property="Foreground" Value="{DynamicResource RadioButtonForegroundDisabled}" />
                    </Style>

                    <Style Selector="^:disabled /template/ Border#RootBorder">
                        <Setter Property="Background" Value="{DynamicResource RadioButtonBackgroundDisabled}" />
                        <Setter Property="BorderBrush" Value="{DynamicResource RadioButtonBorderBrushDisabled}" />
                    </Style>

                    <Style Selector="^:disabled /template/ Ellipse#OuterEllipse">
                        <Setter Property="Stroke" Value="{DynamicResource RadioButtonOuterEllipseStrokeDisabled}" />
                        <Setter Property="Fill" Value="{DynamicResource RadioButtonOuterEllipseFillDisabled}" />
                    </Style>

                    <Style Selector="^:disabled /template/ Ellipse#CheckOuterEllipse">
                        <Setter Property="Stroke" Value="{DynamicResource RadioButtonOuterEllipseCheckedStrokeDisabled}" />
                        <Setter Property="Fill" Value="{DynamicResource RadioButtonOuterEllipseCheckedFillDisabled}" />
                    </Style>

                    <Style Selector="^:disabled /template/ Ellipse#CheckGlyph">
                        <Setter Property="Stroke" Value="{DynamicResource RadioButtonCheckGlyphFillDisabled}" />
                        <Setter Property="Fill" Value="{DynamicResource RadioButtonCheckGlyphStrokeDisabled}" />
                    </Style>


                    <!--  Checked State  -->
                    <Style Selector="^:checked /template/ Ellipse#CheckGlyph">
                        <Setter Property="Opacity" Value="1" />
                    </Style>

                    <Style Selector="^:checked /template/ Ellipse#OuterEllipse">
                        <Setter Property="Opacity" Value="0" />
                    </Style>

                    <Style Selector="^:checked /template/ Ellipse#CheckOuterEllipse">
                        <Setter Property="Opacity" Value="1" />
                    </Style>
                </Style>
            </ListBox.Styles>

        </ListBox>
    </Grid>

</UserControl>

CS:

csharp 复制代码
using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Media.Imaging;
using Avalonia.Media.TextFormatting;
using Avalonia.Metadata;
using Avalonia.Platform;
using Avalonia.Threading;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Timers;

namespace PIMS.Controls;

public partial class PIMSCarousel : UserControl
{
    public PIMSCarousel()
    {
        InitializeComponent();
    }

    private Timer? _timer;
    protected Timer timer
    {
        get
        {
            return _timer ??= new Timer(AutoScrolTimeSpan);
        }
    }

    private void TimerTick(object? sender, ElapsedEventArgs e)
    {
        Dispatcher.UIThread.Post(() =>
        {
            if (cl.SelectedIndex < cl.ItemCount - 1)
            {
                cl.SelectedIndex++;
            }
            else
            {
                cl.SelectedIndex = 0;
            }

            if (lb.Items != null && lb.Items.Count > 0)
            {
                RadioButton rb = lb.Items[cl.SelectedIndex] as RadioButton;
                rb.IsChecked = true;
            }
        });
    }

    protected override void OnLoaded(RoutedEventArgs e)
    {
        base.OnLoaded(e);

        if (IsAutoScroll)
        {
            timer.Elapsed += TimerTick;
            timer.Start();
        }

        cl.SelectedIndex = 0;
    }

    //是否自动滚动
    public static readonly StyledProperty<bool> IsAutoScrollProperty =
        AvaloniaProperty.Register<PIMSCarousel, bool>
        (
            nameof(IsAutoScroll),
            defaultValue: false
        );

    public bool IsAutoScroll
    {
        get => GetValue(IsAutoScrollProperty);
        set => SetValue(IsAutoScrollProperty, value);
    }

    //自动滚动时间间隔
    public static readonly StyledProperty<int> AutoScrolTimeSpanProperty =
        AvaloniaProperty.Register<PIMSCarousel, int>
        (
            nameof(AutoScrolTimeSpan),
            defaultValue: 3000//3秒
        );

    public int AutoScrolTimeSpan
    {
        get => GetValue(AutoScrolTimeSpanProperty);
        set => SetValue(AutoScrolTimeSpanProperty, value);
    }

    private List<string>? _imagePaths;           
    public List<string>? ImagePaths
    {
        get => _imagePaths;
        set
        {
            _imagePaths = value;
            cl.Items?.Clear();
            lb.Items?.Clear();
            for (int index = 0; index < _imagePaths.Count; index++)
            {
                using (var stream = AssetLoader.Open(new Uri(_imagePaths[index]))) 
                {
                    var bt = new Bitmap(stream);
                    cl.Items.Add(new Image() { Source = bt });
                }
               
                RadioButton rb = new RadioButton { Tag = index };
                if (index == 0) rb.IsChecked = true;
                rb.IsCheckedChanged += Rb_IsCheckedChanged;
                lb.Items.Add(rb);               
            }             
        }
    }


    private void Rb_IsCheckedChanged(object? sender, RoutedEventArgs e)
    {
        var rb = sender as RadioButton;
        if(rb.IsChecked.Value)
        {
            if (rb.Tag is int i)
            {
                cl.SelectedIndex = i;
            }
        }      
    } 
}

四、效果

相关推荐
搬砖工程师Cola2 小时前
<C#>.NET WebAPI 的 FromBody ,FromForm ,FromServices等详细解释
开发语言·c#·.net
文牧之3 小时前
PostgreSQL 用户资源管理
运维·数据库·postgresql
春.光明媚4 小时前
网页端调用本地应用打开本地文件(PDF、Word、excel、PPT)
c#·注册表·网页端打开本地文件
zlbcdn6 小时前
C#处理网络传输中不完整的数据流
c#·不完整数据流
FAREWELL000757 小时前
C#进阶学习(九)委托的介绍
开发语言·学习·c#·委托
Paraverse_徐志斌7 小时前
MySQL 线上大表 DDL 如何避免锁表(pt-online-schema-change)
数据库·mysql·ddl·mysql锁·锁表·pt-osc
哈哈幸运7 小时前
MySQL运维三部曲初级篇:从零开始打造稳定高效的数据库环境
linux·运维·数据库·mysql·性能优化
俊俏的萌妹纸7 小时前
FLinkSQL流-小试牛刀
flink·c#·linq
愚公搬代码8 小时前
【愚公系列】《Python网络爬虫从入门到精通》055-Scrapy_Redis分布式爬虫(安装Redis数据库)
数据库·爬虫·python
pwzs8 小时前
深入浅出 MVCC:MySQL 并发背后的多版本世界
数据库·后端·mysql