文章目录
一、加载图片
将三张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"><</Button>
<Button Background="White" Click="Next"
HorizontalAlignment="Right">></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;
}
}
}
}