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;
            }
        }      
    } 
}

四、效果

相关推荐
可喜~可乐32 分钟前
C# WPF开发
microsoft·c#·wpf
微凉的衣柜34 分钟前
微软在AI时代的战略布局和挑战
人工智能·深度学习·microsoft
YashanDB1 小时前
【YashanDB知识库】XMLAGG方法的兼容
数据库·yashandb·崖山数据库
独行soc1 小时前
#渗透测试#漏洞挖掘#红蓝攻防#护网#sql注入介绍11基于XML的SQL注入(XML-Based SQL Injection)
数据库·安全·web安全·漏洞挖掘·sql注入·hw·xml注入
风间琉璃""2 小时前
bugkctf 渗透测试1超详细版
数据库·web安全·网络安全·渗透测试·内网·安全工具
drebander2 小时前
SQL 实战-巧用 CASE WHEN 实现条件分组与统计
大数据·数据库·sql
IvorySQL2 小时前
IvorySQL 4.0 发布:全面支持 PostgreSQL 17
数据库·postgresql·开源数据库·国产数据库·ivorysql
18号房客3 小时前
高级sql技巧进阶教程
大数据·数据库·数据仓库·sql·mysql·时序数据库·数据库架构
Dawnㅤ3 小时前
使用sql实现将一张表的某些字段数据存到另一种表里
数据库·sql
张声录13 小时前
【ETCD】【实操篇(十二)】分布式系统中的“王者之争”:基于ETCD的Leader选举实战
数据库·etcd