XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEToolBox

【WPF】XFE工具箱

公开
关注 0 Fork 0 Star 0
返回提交历史

XFEstudio/XFEToolBox

初步完善轮播图

e36bd2e
XFE工作室室长 <mail@xfegzs.com>
提交于

代码差异

5 个文件 +162 -36
Modified XFEToolBox/Views/Controls/Carousel.xaml +13 -2
@@ -5,7 +5,7 @@
5 5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6 6 xmlns:local="clr-namespace:XFEToolBox.Views.Controls"
7 7 mc:Ignorable="d"
8 d:DesignHeight="450" d:DesignWidth="800">
8 d:DesignHeight="250" d:DesignWidth="600">
9 9 <Grid>
10 10 <Grid.ColumnDefinitions>
11 11 <ColumnDefinition Width="50"/>
@@ -16,6 +16,17 @@
16 16 <RowDefinition Height="*"/>
17 17 <RowDefinition Height="30"/>
18 18 </Grid.RowDefinitions>
19 <Image Source="{Binding }"/>
19
20 <!-- Main image -->
21 <Border Grid.Column="1" Grid.Row="0" CornerRadius="8" Background="LightGray" ClipToBounds="True" Margin="5">
22 <Image Stretch="UniformToFill" Source="{Binding CurrentImageSource, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
23 </Border>
24
25 <!-- Prev/Next buttons -->
26 <Button Grid.Column="0" Grid.Row="0" Width="36" Height="36" VerticalAlignment="Center" HorizontalAlignment="Center" Click="PrevButton_Click">◀</Button>
27 <Button Grid.Column="2" Grid.Row="0" Width="36" Height="36" VerticalAlignment="Center" HorizontalAlignment="Center" Click="NextButton_Click">▶</Button>
28
29 <!-- Simple position text -->
30 <TextBlock Grid.Row="1" Grid.ColumnSpan="3" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="Gray" FontSize="12" Text="{Binding Path=PositionText, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
20 31 </Grid>
21 32 </UserControl>
Modified XFEToolBox/Views/Controls/Carousel.xaml.cs +97 -15
@@ -1,4 +1,6 @@
1 using System.Windows;
1 using System.Collections.ObjectModel;
2 using System.ComponentModel;
3 using System.Windows;
2 4 using System.Windows.Controls;
3 5 using System.Windows.Media;
4 6
@@ -7,12 +9,42 @@ namespace XFEToolBox.Views.Controls;
7 9 /// <summary>
8 10 /// Carousel.xaml 的交互逻辑
9 11 /// </summary>
10 public partial class Carousel : UserControl
12 public partial class Carousel : UserControl, INotifyPropertyChanged
11 13 {
12 private int currentIndex = 0;
14 private int currentIndex = -1;
13 15 private bool isMouseOn = false;
16 private System.Windows.Threading.DispatcherTimer? timer;
17
14 18 #region DependencyProperty
15 public List<ImageSource> ImageList { get; set; } = [];
19 public ObservableCollection<ImageSource> ImageList
20 {
21 get { return (ObservableCollection<ImageSource>)GetValue(ImageListProperty); }
22 set { SetValue(ImageListProperty, value); }
23 }
24
25 public static readonly DependencyProperty ImageListProperty = DependencyProperty.Register(
26 "ImageList", typeof(ObservableCollection<ImageSource>), typeof(Carousel), new PropertyMetadata(new ObservableCollection<ImageSource>(), OnImageListChanged));
27
28 private static void OnImageListChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
29 {
30 if (d is Carousel c)
31 {
32 if (e.OldValue is ObservableCollection<ImageSource> old)
33 old.CollectionChanged -= c.ImageList_CollectionChanged;
34 if (e.NewValue is ObservableCollection<ImageSource> neu)
35 neu.CollectionChanged += c.ImageList_CollectionChanged;
36
37 c.currentIndex = -1;
38 c.UpdateImage();
39 }
40 }
41
42 private void ImageList_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
43 {
44 if (currentIndex >= ImageList.Count)
45 currentIndex = ImageList.Count - 1;
46 UpdateImage();
47 }
16 48
17 49 public ImageSource CurrentImageSource
18 50 {
@@ -21,38 +53,88 @@ public partial class Carousel : UserControl
21 53 }
22 54 public static readonly DependencyProperty CurrentImageSourceProperty = DependencyProperty.Register("CurrentImageSource", typeof(ImageSource), typeof(Carousel), new PropertyMetadata(null));
23 55
24 public ImageSource AfterImageSource
56 public string PositionText
25 57 {
26 get { return (ImageSource)GetValue(AfterImageSourceProperty); }
27 set { SetValue(AfterImageSourceProperty, value); }
58 get { return (string)GetValue(PositionTextProperty); }
59 private set { SetValue(PositionTextProperty, value); }
28 60 }
29 public static readonly DependencyProperty AfterImageSourceProperty = DependencyProperty.Register("AfterImageSource", typeof(ImageSource), typeof(Carousel), new PropertyMetadata(null));
61 public static readonly DependencyProperty PositionTextProperty = DependencyProperty.Register("PositionText", typeof(string), typeof(Carousel), new PropertyMetadata(string.Empty));
30 62 #endregion
63
31 64 public Carousel()
32 65 {
66 InitializeComponent();
67
33 68 Loaded += Carousel_Loaded;
69 Unloaded += Carousel_Unloaded;
70
34 71 MouseEnter += (s, e) => isMouseOn = true;
35 72 MouseLeave += (s, e) => isMouseOn = false;
36 73 MouseMove += (s, e) => isMouseOn = true;
37 InitializeComponent();
74
75 DataContext = this;
38 76 }
39 77
40 78 private void Carousel_Loaded(object sender, RoutedEventArgs e)
41 79 {
42 var timer = new System.Windows.Threading.DispatcherTimer
80 if (timer == null)
43 81 {
44 Interval = TimeSpan.FromSeconds(3)
45 };
46 timer.Tick += Timer_Tick;
82 timer = new System.Windows.Threading.DispatcherTimer
83 {
84 Interval = TimeSpan.FromSeconds(3)
85 };
86 timer.Tick += Timer_Tick;
87 }
47 88 timer.Start();
89 UpdateImage();
90 }
91
92 private void Carousel_Unloaded(object sender, RoutedEventArgs e)
93 {
94 timer?.Stop();
48 95 }
49 96
50 97 private void Timer_Tick(object? sender, EventArgs e)
51 98 {
52 if (!isMouseOn && ImageList.Count > 0)
99 if (!isMouseOn && ImageList != null && ImageList.Count > 0)
53 100 {
54 101 currentIndex = (currentIndex + 1) % ImageList.Count;
55 CurrentImageSource = ImageList[currentIndex];
102 UpdateImage();
103 }
104 }
105
106 private void UpdateImage()
107 {
108 if (ImageList == null || ImageList.Count == 0)
109 {
110 CurrentImageSource = null;
111 PositionText = string.Empty;
112 return;
56 113 }
114
115 if (currentIndex < 0)
116 currentIndex = 0;
117
118 CurrentImageSource = ImageList[currentIndex];
119 PositionText = $"{currentIndex + 1}/{ImageList.Count}";
120 OnPropertyChanged(nameof(CurrentImageSource));
121 OnPropertyChanged(nameof(PositionText));
122 }
123
124 private void PrevButton_Click(object sender, RoutedEventArgs e)
125 {
126 if (ImageList == null || ImageList.Count == 0) return;
127 currentIndex = (currentIndex - 1 + ImageList.Count) % ImageList.Count;
128 UpdateImage();
57 129 }
130
131 private void NextButton_Click(object sender, RoutedEventArgs e)
132 {
133 if (ImageList == null || ImageList.Count == 0) return;
134 currentIndex = (currentIndex + 1) % ImageList.Count;
135 UpdateImage();
136 }
137
138 public event PropertyChangedEventHandler? PropertyChanged;
139 protected void OnPropertyChanged(string name) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
58 140 }
Modified XFEToolBox/Views/Pages/MainPage.xaml +13 -16
@@ -9,21 +9,18 @@
9 9 d:DesignHeight="450" d:DesignWidth="800"
10 10 Title="MainPage" Loaded="Page_Loaded">
11 11 <Grid>
12 <Grid.ColumnDefinitions>
13 <ColumnDefinition Width="2*"/>
14 <ColumnDefinition Width="*"/>
15 </Grid.ColumnDefinitions>
16 <Grid.RowDefinitions>
17 <RowDefinition Height="Auto"/>
18 <RowDefinition Height="2*"/>
19 <RowDefinition Height="*"/>
20 </Grid.RowDefinitions>
21 <TextBlock Margin="10,0" Text="最近使用" Foreground="{DynamicResource BackgroundColor}" FontSize="15" FontWeight="Bold"/>
22 <Border Grid.Row="1" Grid.ColumnSpan="2" CornerRadius="15" Background="White" Margin="10">
23 <ScrollViewer VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Disabled" Padding="5">
24 <WrapPanel>
25 </WrapPanel>
26 </ScrollViewer>
27 </Border>
12 <ctr:SmoothScrollViewer>
13 <ScrollViewer.Resources>
14 <Style TargetType="ScrollBar" BasedOn="{StaticResource ConsoleScrollBar}"/>
15 </ScrollViewer.Resources>
16 <StackPanel Orientation="Vertical">
17 <ctr:Carousel x:Name="mainCarousel" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Center" Height="220"/>
18 <TextBlock Margin="10,0" Text="最近使用" Foreground="{DynamicResource BackgroundColor}" FontSize="15" FontWeight="Bold"/>
19 <Border CornerRadius="15" Background="White" Margin="10" Padding="10">
20 <WrapPanel MinHeight="500">
21 </WrapPanel>
22 </Border>
23 </StackPanel>
24 </ctr:SmoothScrollViewer>
28 25 </Grid>
29 26 </Page>
Modified XFEToolBox/Views/Pages/MainPage.xaml.cs +38 -2
@@ -1,6 +1,7 @@
1 1 using System.Windows.Controls;
2 using XFEExtension.NetCore.FileExtension;
3 using XFEToolBox.Utilities;
2 using System.Windows.Media;
3 using System.Windows.Media.Imaging;
4 using XFEToolBox.Views.Controls;
4 5
5 6 namespace XFEToolBox.Views.Pages;
6 7
@@ -18,5 +19,40 @@ public partial class MainPage : Page
18 19
19 20 private void Page_Loaded(object sender, System.Windows.RoutedEventArgs e)
20 21 {
22 var carousel = this.FindName("mainCarousel") as Carousel;
23 if (carousel != null)
24 {
25 carousel.ImageList.Clear();
26 for (int i = 1; i <= 4; i++)
27 {
28 var img = CreatePlaceholderImage($"示例 {i}", 800, 450);
29 carousel.ImageList.Add(img);
30 }
31 }
32 }
33
34 private ImageSource CreatePlaceholderImage(string text, int width, int height)
35 {
36 var dv = new DrawingVisual();
37 using (var dc = dv.RenderOpen())
38 {
39 // Background
40 var brush = new LinearGradientBrush(Color.FromRgb(240, 240, 240), Color.FromRgb(200, 200, 255), 45);
41 dc.DrawRectangle(brush, null, new System.Windows.Rect(0, 0, width, height));
42
43 // Centered text
44 var formatted = new FormattedText(text,
45 System.Globalization.CultureInfo.CurrentCulture,
46 System.Windows.FlowDirection.LeftToRight,
47 new Typeface("Segoe UI"), 48, Brushes.Gray, 1.0);
48
49 var pt = new System.Windows.Point((width - formatted.Width) / 2, (height - formatted.Height) / 2);
50 dc.DrawText(formatted, pt);
51 }
52
53 var bmp = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
54 bmp.Render(dv);
55 bmp.Freeze();
56 return bmp;
21 57 }
22 58 }
Modified XFEToolBox/XFEToolBox.csproj +1 -1
@@ -2,7 +2,7 @@
2 2
3 3 <PropertyGroup>
4 4 <OutputType>WinExe</OutputType>
5 <TargetFramework>net9.0-windows</TargetFramework>
5 <TargetFramework>net10.0-windows</TargetFramework>
6 6 <Nullable>enable</Nullable>
7 7 <ImplicitUsings>enable</ImplicitUsings>
8 8 <UseWPF>true</UseWPF>