返回提交历史
Modified
XFEToolBox/Profiles/CacheProfiles/AppCacheProfile.cs
+2
-2
Modified
XFEToolBox/Profiles/CrossVersionProfiles/ConsoleProfile.cs
+1
-1
Modified
XFEToolBox/Profiles/CrossVersionProfiles/DownloadProfile.cs
+1
-1
Modified
XFEToolBox/Profiles/CrossVersionProfiles/SystemProfile.cs
+1
-1
Added
XFEToolBox/Utilities/Helpers/BilibiliHelper.cs
+17
-0
Modified
XFEToolBox/ViewModel/Pages/MainPageViewModel.cs
+20
-1
Modified
XFEToolBox/Views/Controls/Carousel.xaml
+36
-14
Modified
XFEToolBox/Views/Controls/Carousel.xaml.cs
+57
-3
Modified
XFEToolBox/Views/Pages/MainPage.xaml
+1
-1
Modified
XFEToolBox/Views/Pages/MainPage.xaml.cs
+3
-39
Modified
XFEToolBox/XFEToolBox.csproj
+5
-5
XFEstudio/XFEToolBox
完善主页轮播图的图片获取功能
2ac5528
代码差异
11 个文件
+144
-68
@@ -3,10 +3,10 @@ using XFEToolBox.Core.Model;
3
3
4
4
namespace XFEToolBox.Profiles.CacheProfiles;
5
5
6
public partial class AppCacheProfile
6
public partial class AppCacheProfile : XFEProfile
7
7
{
8
8
[ProfileProperty]
9
9
private string noticeText = "";
10
public AppCacheProfile() => ProfilePath = @$"{AppPath.CacheProfile}\{typeof(AppCacheProfile)}.xprofile";
11
10
11
public AppCacheProfile() => ProfilePath = @$"{AppPath.CacheProfile}\{typeof(AppCacheProfile)}.xprofile";
12
12
}
@@ -3,7 +3,7 @@ using XFEToolBox.Core.Model;
3
3
4
4
namespace XFEToolBox.Profiles.CrossVersionProfiles;
5
5
6
public partial class ConsoleProfile
6
public partial class ConsoleProfile : XFEProfile
7
7
{
8
8
/// <summary>
9
9
/// 控制台端口
@@ -3,7 +3,7 @@ using XFEToolBox.Core.Model;
3
3
4
4
namespace XFEToolBox.Profiles.CrossVersionProfiles;
5
5
6
public partial class DownloadProfile
6
public partial class DownloadProfile : XFEProfile
7
7
{
8
8
/// <summary>
9
9
/// 是否使用一般的下载方式
@@ -4,7 +4,7 @@ using XFEToolBox.Views.Windows;
4
4
5
5
namespace XFEToolBox.Profiles.CrossVersionProfiles;
6
6
7
public partial class SystemProfile
7
public partial class SystemProfile : XFEProfile
8
8
{
9
9
/// <summary>
10
10
/// 当前窗口DPI缩放
@@ -0,0 +1,17 @@
1
using System.Net.Http;
2
using XFEExtension.NetCore.XFETransform.JsonConverter;
3
4
namespace XFEToolBox.Utilities.Helpers;
5
6
public static class BilibiliHelper
7
{
8
public static async Task<List<Dictionary<string, ValueNode>>> GetSeasonVideoList(string seasonId = "3641758")
9
{
10
var client = new HttpClient();
11
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36 Edg/145.0.0.0");
12
QueryableJsonNode jsonNode = await client.GetStringAsync($"https://api.bilibili.com/x/polymer/web-space/seasons_archives_list?mid=200494622&season_id={seasonId}&sort_reverse=false&page_size=30&page_num=1&web_location=333.1387");
13
if (jsonNode["data"]?["archives"]?["package:list", "aid", "bvid", "pic", "title"].PackageInListObject() is List<Dictionary<string, ValueNode>> subJsonNodes)
14
return subJsonNodes;
15
return [];
16
}
17
}
@@ -1,7 +1,26 @@
1
1
using CommunityToolkit.Mvvm.ComponentModel;
2
using System.Windows.Media;
3
using System.Windows.Media.Imaging;
4
using XFEToolBox.Utilities.Helpers;
5
using XFEToolBox.Views.Pages;
2
6
3
7
namespace XFEToolBox.ViewModel.Pages;
4
8
5
9
public partial class MainPageViewModel : ObservableObject
6
10
{
7
}
11
public MainPage MainPage { get; set; }
12
public MainPageViewModel(MainPage mainPage)
13
{
14
MainPage = mainPage;
15
MainPage.Loaded += MainPage_Loaded;
16
}
17
18
private async void MainPage_Loaded(object sender, System.Windows.RoutedEventArgs e)
19
{
20
var videoInfoList = await BilibiliHelper.GetSeasonVideoList();
21
foreach (var videoInfo in videoInfoList)
22
{
23
MainPage.mainCarousel.AddItem(new BitmapImage(new Uri(videoInfo["pic"].ToString())), videoInfo["title"].ToString());
24
}
25
}
26
}
@@ -25,7 +25,11 @@
25
25
<!-- Center card column with rounded border and image -->
26
26
<Border Grid.Column="1" CornerRadius="12" Background="#F0EEF6" Padding="8">
27
27
<Grid>
28
<Image x:Name="PART_Image" Source="{Binding CurrentImageSource, RelativeSource={RelativeSource AncestorType=UserControl}}" Stretch="UniformToFill" ClipToBounds="True"/>
28
<!-- Two images for cross-fade -->
29
<Grid>
30
<Image x:Name="ImageBack" Stretch="UniformToFill" Opacity="0" ClipToBounds="True"/>
31
<Image x:Name="ImageFront" Stretch="UniformToFill" Opacity="1" ClipToBounds="True"/>
32
</Grid>
29
33
30
34
<!-- Bottom acrylic bar inside center card -->
31
35
<Border VerticalAlignment="Bottom" Margin="8" CornerRadius="8" Background="#CCFFFFFF" Height="64" Padding="12">
@@ -47,21 +51,39 @@
47
51
<ItemsControl.ItemTemplate>
48
52
<DataTemplate>
49
53
<Border Background="Transparent" Padding="6" Cursor="Hand" MouseLeftButtonUp="Indicator_MouseLeftButtonUp">
50
<Ellipse Width="10" Height="10" Fill="#888" Opacity="0.5">
51
<Ellipse.Style>
52
<Style TargetType="Ellipse">
53
<Style.Triggers>
54
<DataTrigger Binding="{Binding IsSelected}" Value="True">
55
<Setter Property="Fill" Value="#6A5ACD"/>
56
<Setter Property="Opacity" Value="1"/>
57
<Setter Property="Width" Value="14"/>
58
<Setter Property="Height" Value="14"/>
59
</DataTrigger>
60
</Style.Triggers>
61
</Style>
62
</Ellipse.Style>
54
<Ellipse x:Name="Dot" Width="10" Height="10" Opacity="0.5" RenderTransformOrigin="0.5,0.5">
55
<Ellipse.Fill>
56
<SolidColorBrush Color="#888888"/>
57
</Ellipse.Fill>
58
<Ellipse.RenderTransform>
59
<ScaleTransform ScaleX="1" ScaleY="1"/>
60
</Ellipse.RenderTransform>
63
61
</Ellipse>
64
62
</Border>
63
<DataTemplate.Triggers>
64
<DataTrigger Binding="{Binding IsSelected}" Value="True">
65
<DataTrigger.EnterActions>
66
<BeginStoryboard Name="EnterDot">
67
<Storyboard>
68
<ColorAnimation Storyboard.TargetName="Dot" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" To="#FF6A5ACD" Duration="0:0:0.12"/>
69
<DoubleAnimation Storyboard.TargetName="Dot" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.12"/>
70
<DoubleAnimation Storyboard.TargetName="Dot" Storyboard.TargetProperty="RenderTransform.(ScaleTransform.ScaleX)" To="1.4" Duration="0:0:0.18"/>
71
<DoubleAnimation Storyboard.TargetName="Dot" Storyboard.TargetProperty="RenderTransform.(ScaleTransform.ScaleY)" To="1.4" Duration="0:0:0.18"/>
72
</Storyboard>
73
</BeginStoryboard>
74
</DataTrigger.EnterActions>
75
<DataTrigger.ExitActions>
76
<BeginStoryboard Name="ExitDot">
77
<Storyboard>
78
<ColorAnimation Storyboard.TargetName="Dot" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" To="#888888" Duration="0:0:0.12"/>
79
<DoubleAnimation Storyboard.TargetName="Dot" Storyboard.TargetProperty="Opacity" To="0.5" Duration="0:0:0.12"/>
80
<DoubleAnimation Storyboard.TargetName="Dot" Storyboard.TargetProperty="RenderTransform.(ScaleTransform.ScaleX)" To="1" Duration="0:0:0.18"/>
81
<DoubleAnimation Storyboard.TargetName="Dot" Storyboard.TargetProperty="RenderTransform.(ScaleTransform.ScaleY)" To="1" Duration="0:0:0.18"/>
82
</Storyboard>
83
</BeginStoryboard>
84
</DataTrigger.ExitActions>
85
</DataTrigger>
86
</DataTemplate.Triggers>
65
87
</DataTemplate>
66
88
</ItemsControl.ItemTemplate>
67
89
</ItemsControl>
@@ -4,6 +4,8 @@ using System.Windows;
4
4
using System.Windows.Controls;
5
5
using System.Windows.Input;
6
6
using System.Windows.Media;
7
using System.Windows.Media.Animation;
8
using System.Windows.Media.Imaging;
7
9
8
10
namespace XFEToolBox.Views.Controls;
9
11
@@ -95,6 +97,9 @@ public partial class Carousel : UserControl, INotifyPropertyChanged
95
97
DataContext = this;
96
98
}
97
99
100
private Image ImageFrontControl => (Image)FindName("ImageFront");
101
private Image ImageBackControl => (Image)FindName("ImageBack");
102
98
103
private void Carousel_Loaded(object sender, RoutedEventArgs e)
99
104
{
100
105
if (timer == null)
@@ -106,7 +111,7 @@ public partial class Carousel : UserControl, INotifyPropertyChanged
106
111
timer.Tick += Timer_Tick;
107
112
}
108
113
timer.Start();
109
UpdateImage();
114
UpdateImage(true);
110
115
}
111
116
112
117
private void Carousel_Unloaded(object sender, RoutedEventArgs e)
@@ -123,7 +128,7 @@ public partial class Carousel : UserControl, INotifyPropertyChanged
123
128
}
124
129
}
125
130
126
private void UpdateImage()
131
private void UpdateImage(bool initial = false)
127
132
{
128
133
if (ImageList == null || ImageList.Count == 0)
129
134
{
@@ -143,6 +148,50 @@ public partial class Carousel : UserControl, INotifyPropertyChanged
143
148
var item = ImageList[currentIndex];
144
149
CurrentImageSource = item?.Image;
145
150
CurrentTitle = item?.Title ?? string.Empty;
151
152
// Cross-fade using named image controls
153
try
154
{
155
var front = ImageFrontControl;
156
var back = ImageBackControl;
157
158
if (front == null || back == null)
159
return;
160
161
// move front to back
162
if (front.Source != null)
163
{
164
back.Source = front.Source;
165
back.Opacity = 1;
166
}
167
else
168
{
169
back.Source = null;
170
back.Opacity = 0;
171
}
172
173
// set front to new image
174
front.Source = item?.Image;
175
176
if (initial)
177
{
178
front.Opacity = 1;
179
back.Opacity = 0;
180
}
181
else
182
{
183
var fadeOut = new DoubleAnimation(1, 0, new Duration(TimeSpan.FromMilliseconds(500))) { EasingFunction = new QuadraticEase { EasingMode = EasingMode.EaseOut } };
184
var fadeIn = new DoubleAnimation(0, 1, new Duration(TimeSpan.FromMilliseconds(500))) { EasingFunction = new QuadraticEase { EasingMode = EasingMode.EaseOut } };
185
186
back.BeginAnimation(UIElement.OpacityProperty, fadeOut);
187
front.BeginAnimation(UIElement.OpacityProperty, fadeIn);
188
}
189
}
190
catch
191
{
192
// ignore animation errors in design time
193
}
194
146
195
OnPropertyChanged(nameof(CurrentImageSource));
147
196
OnPropertyChanged(nameof(CurrentTitle));
148
197
}
@@ -177,11 +226,16 @@ public partial class Carousel : UserControl, INotifyPropertyChanged
177
226
// Public API helpers
178
227
public void AddItem(ImageSource image, string title)
179
228
{
229
var frozen = image as BitmapSource;
230
if (frozen != null && frozen.CanFreeze)
231
{
232
try { frozen.Freeze(); } catch { }
233
}
180
234
ImageList.Add(new CarouselImageItem { Image = image, Title = title });
181
235
if (ImageList.Count == 1)
182
236
{
183
237
currentIndex = 0;
184
UpdateImage();
238
UpdateImage(true);
185
239
}
186
240
}
187
241
@@ -7,7 +7,7 @@
7
7
xmlns:local="clr-namespace:XFEToolBox.Views.Pages"
8
8
mc:Ignorable="d"
9
9
d:DesignHeight="450" d:DesignWidth="800"
10
Title="MainPage" Loaded="Page_Loaded">
10
Title="MainPage">
11
11
<Grid>
12
12
<ctr:SmoothScrollViewer>
13
13
<ScrollViewer.Resources>
@@ -1,5 +1,6 @@
1
1
using System.Windows.Controls;
2
2
using System.Windows.Media;
3
using XFEToolBox.ViewModel.Pages;
3
4
using XFEToolBox.Views.Controls;
4
5
5
6
namespace XFEToolBox.Views.Pages;
@@ -10,48 +11,11 @@ namespace XFEToolBox.Views.Pages;
10
11
public partial class MainPage : Page
11
12
{
12
13
public static MainPage? Current { get; set; } = new();
14
public MainPageViewModel ViewModel { get; set; }
13
15
public MainPage()
14
16
{
15
17
Current = this;
18
ViewModel = new(this);
16
19
InitializeComponent();
17
20
}
18
19
private void Page_Loaded(object sender, System.Windows.RoutedEventArgs e)
20
{
21
var carousel = this.FindName("mainCarousel") as Carousel;
22
if (carousel != null)
23
{
24
carousel.ImageList.Clear();
25
for (int i = 1; i <= 4; i++)
26
{
27
var img = CreatePlaceholderImage($"示例 {i}", 800, 450);
28
carousel.AddItem(img, $"示例 {i}");
29
}
30
}
31
}
32
33
private ImageSource CreatePlaceholderImage(string text, int width, int height)
34
{
35
var dv = new System.Windows.Media.DrawingVisual();
36
using (var dc = dv.RenderOpen())
37
{
38
// Background
39
var brush = new System.Windows.Media.LinearGradientBrush(System.Windows.Media.Color.FromRgb(245, 245, 250), System.Windows.Media.Color.FromRgb(220, 220, 255), 45);
40
dc.DrawRectangle(brush, null, new System.Windows.Rect(0, 0, width, height));
41
42
// Centered text
43
var formatted = new System.Windows.Media.FormattedText(text,
44
System.Globalization.CultureInfo.CurrentCulture,
45
System.Windows.FlowDirection.LeftToRight,
46
new System.Windows.Media.Typeface("Segoe UI"), 48, System.Windows.Media.Brushes.Gray, 1.0);
47
48
var pt = new System.Windows.Point((width - formatted.Width) / 2, (height - formatted.Height) / 2);
49
dc.DrawText(formatted, pt);
50
}
51
52
var bmp = new System.Windows.Media.Imaging.RenderTargetBitmap(width, height, 96, 96, System.Windows.Media.PixelFormats.Pbgra32);
53
bmp.Render(dv);
54
bmp.Freeze();
55
return bmp;
56
}
57
21
}
@@ -42,13 +42,13 @@
42
42
</ItemGroup>
43
43
44
44
<ItemGroup>
45
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
46
<PackageReference Include="XFEExtension.NetCore" Version="3.0.2" />
47
<PackageReference Include="XFEExtension.NetCore.AutoConfig" Version="1.1.1" />
45
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
46
<PackageReference Include="XFEExtension.NetCore" Version="3.3.10" />
47
<PackageReference Include="XFEExtension.NetCore.AutoConfig" Version="2.0.7" />
48
48
<PackageReference Include="XFEExtension.NetCore.AutoPath" Version="1.0.1" />
49
<PackageReference Include="XFEExtension.NetCore.InputSimulator" Version="2.2.0" />
49
<PackageReference Include="XFEExtension.NetCore.InputSimulator" Version="2.3.0" />
50
50
<PackageReference Include="XFEExtension.NetCore.TodoHighLight" Version="1.0.0" />
51
<PackageReference Include="XFEExtension.NetCore.XFEConsole" Version="1.0.2" />
51
<PackageReference Include="XFEExtension.NetCore.XFEConsole" Version="1.2.3" />
52
52
</ItemGroup>
53
53
54
54
<ItemGroup>