前言:winfrom转wpf用久的熟手说得最多的是,转回去做winfrom难。。当时不明白。。做一个就知道了。
WPF音乐播放器
入口主程序
FontFamily="Microsoft YaHei" FontSize="12" FontWeight="ExtraLight"
居中显示
WindowStartupLocation="CenterScreen" ResizeMode="NoResize"
Title="音娱乐行音乐播放器" Height="600" Width="1010"
无边框
<WindowChrome.WindowChrome>
<WindowChrome GlassFrameThickness="1"/>
</WindowChrome.WindowChrome>
StackPanel 块 Orientation="Horizontal" 水平显示 HorizontalAlignment="Center" 居中
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Border Width="28" Height="28" CornerRadius="10">
<Border.Background>
<ImageBrush ImageSource="../Assets/Images/Logo.png" Stretch="UniformToFill"
Viewport="-0.3,-0.3,1.6,1.6"
Opacity="0.5"/>
</Border.Background>
<TextBlock Text="" FontFamily="{StaticResource FF}" VerticalAlignment="Center" HorizontalAlignment="Left"
FontSize="20" Foreground="ForestGreen" Height="19" Width="18" Margin="-14,0,0,0">
<TextBlock.Effect>
<DropShadowEffect BlurRadius="5" Color="ForestGreen" ShadowDepth="0" Opacity="0.5"/>
</TextBlock.Effect>
</TextBlock>
</Border>
<TextBlock Text="音娱乐行播放器" VerticalAlignment="Center" Margin="10,0,0,0" Foreground="Orange"
FontSize="13" FontWeight="Bold"/>
</StackPanel>
**************
菜单栏目
<StackPanel Grid.Row="1">
<RadioButton Content="首页" Tag="" Style="{StaticResource MenuButtonStyle}" IsChecked="True"/>
<RadioButton Content="有声动态谱" Tag="" Style="{StaticResource MenuButtonStyle}" IsChecked="True"/>
<RadioButton Content="精品歌单" Tag="" Style="{StaticResource MenuButtonStyle}"/>
<RadioButton Content="歌手推荐" Tag="" Style="{StaticResource MenuButtonStyle}"/>
<RadioButton Content="单曲排行" Tag="" Style="{StaticResource MenuButtonStyle}"/>
<Label Content="音乐分类" Tag="" Style="{StaticResource MenuLabelStyle}"/>
<UniformGrid Columns="3" Margin="40,0,10,0">
<RadioButton Content="流行" Style="{StaticResource ClassButtonStyle}"/>
<RadioButton Content="民谣" Style="{StaticResource ClassButtonStyle}"/>
<RadioButton Content="电子" Style="{StaticResource ClassButtonStyle}"/>
<RadioButton Content="舞曲" Style="{StaticResource ClassButtonStyle}"/>
<RadioButton Content="说唱" Style="{StaticResource ClassButtonStyle}"/>
<RadioButton Content="轻音乐" Style="{StaticResource ClassButtonStyle}"/>
<RadioButton Content="爵士" Style="{StaticResource ClassButtonStyle}"/>
<RadioButton Content="乡村" Style="{StaticResource ClassButtonStyle}"/>
<RadioButton Content="更多" Style="{StaticResource ClassButtonStyle}"/>
</UniformGrid>
<Label Content="我的音乐" Tag="" Style="{StaticResource MenuLabelStyle}"/>
<ItemsControl ItemsSource="{Binding SList}" Margin="40,0,10,0">
<ItemsControl.ItemTemplate>
<DataTemplate>
<RadioButton Content="{Binding Header}" Tag="{Binding Icon}"
Style="{StaticResource SheetButtonStyle}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
样式控件
MenuButtonStyle 样式
// <Border 没法放两个以上对象 需要<StackPanel 包起来 <TextBlock 图标 <ContentPresente 内容
// <ControlTemplate.Triggers> 控件触发器 <Style.Triggers>样式触发器
<Style TargetType="RadioButton" x:Key="MenuButtonStyle">
<Setter Property="Foreground" Value="#B1AFBA"/>
<Setter Property="GroupName" Value="A"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RadioButton">
<Border BorderBrush="Transparent" BorderThickness="2,0,0,0"
Name="border" Height="30" Margin="0,3">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left"
VerticalAlignment="Center" Margin="20,0,0,0">
<TextBlock Text="{TemplateBinding Tag}" FontFamily="{StaticResource FF}"
FontSize="18"/>
<ContentPresenter VerticalAlignment="Center" Margin="10,0,0,0"/>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="border" Property="BorderBrush" Value="#AA6063FB"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Foreground" Value="#6063FB"/>
</Trigger>
</Style.Triggers>
</Style>
MenuLabelStyle 样式
<Style TargetType="Label" x:Key="MenuLabelStyle">
<Setter Property="Foreground" Value="#555"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Label">
<Border BorderBrush="Transparent" BorderThickness="2,0,0,0"
Name="border" Height="30" Margin="0,3">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left"
VerticalAlignment="Center" Margin="20,0,0,0">
<TextBlock Text="{TemplateBinding Tag}" FontFamily="{StaticResource FF}"
FontSize="18"/>
<ContentPresenter VerticalAlignment="Center" Margin="10,0,0,0"/>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
ClassButtonStyle 样式
<Style TargetType="RadioButton" x:Key="ClassButtonStyle">
<Setter Property="Foreground" Value="#B1AFBA"/>
<Setter Property="FontSize" Value="11"/>
<Setter Property="GroupName" Value="A"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RadioButton">
<Border Height="24" Background="#EEE" Margin="1" CornerRadius="3"
Name="border">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="#116063FB"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="border" Property="BorderBrush" Value="#AA6063FB"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Foreground" Value="#6063FB"/>
</Trigger>
</Style.Triggers>
</Style>
后台绑定数据
指定关系
DataContext = new MainViewModel();
右侧内容
<!--右侧内容-->
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBox Height="28" Width="180" HorizontalAlignment="Left"
Style="{StaticResource SearchTextBoxStyle}"
VerticalContentAlignment="Center" Margin="30,0"/>
<!--页面内容 VerticalScrollBarVisibility="Hidden" 隐藏滚动条-->
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Hidden">
<Grid Margin="30,0">
<p:FirstPage/> fistpage 页面
</Grid>
</ScrollViewer>
</Grid>
爬虫
数据绑定
<TextBlock Text="热门专辑" VerticalAlignment="Center" FontWeight="Bold"
Foreground="#555"/>
<ListBox Grid.Row="1" BorderThickness="0" Background="Transparent"
ItemsSource="{Binding AlbumList}" ScrollViewer.HorizontalScrollBarVisibility="Hidden">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal"/> 水平显示
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle> 模板
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem"> 关键 控件模板
<ContentPresenter Margin="5"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate> 数据模板
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Border Width="100" Height="100" CornerRadius="5" >
<Border.Background>
<ImageBrush ImageSource="{Binding Cover}"/>
</Border.Background>
<Border.Effect>
<DropShadowEffect BlurRadius="5"
ShadowDepth="0" Color="Gray" Opacity="0.5"/>
</Border.Effect>
</Border>
数据列表绑定
数据细节处理
ps:学wpf没有个大屏是个阻力哈哈哈
播放控制器
DataContext.PlayDownloadCommand,RelativeSource
播放命令指向信息
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid Background="Transparent" Name="root">
<ContentPresenter/>
<TextBlock Grid.Column="3"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Margin="100,0,0,0"
FontSize="11"
Name="tb_control"
Visibility="Collapsed">
<Hyperlink TextDecorations="None"
Command="{Binding DataContext.PlayDownloadCommand,RelativeSource={RelativeSource AncestorType=Window}}"
CommandParameter="{Binding}">播放</Hyperlink>
<Hyperlink TextDecorations="None">添加</Hyperlink>
</TextBlock>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="root" Property="Background" Value="#44ECEAF6"/>
<Setter TargetName="tb_control" Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
指向信息帮助类 有点深入自己看
public class Command<T> : ICommand
{
public event EventHandler? CanExecuteChanged;
public bool CanExecute(object? parameter)
{
return true;
}
public void Execute(object? parameter)
{
dynamic param = parameter;
DoExecute?.Invoke(param);
}
public Action<T> DoExecute { get; set; }
public Command(Action<T> action)
{
DoExecute = action;
}
}
public class Command : Command<object>
{
public Command(Action action) : base(obj => action?.Invoke()) { }
}
其他类似
小经验
分界线 深吭来了
public async void Play(SongModel song)
{
var options = new LaunchOptions { Headless = true };
// 这里有个深坑哈 先要跑一边 下载运行环境 后 注释掉
// await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultChromiumRevision);
//注意 两个using
using (var browser = await Puppeteer.LaunchAsync(options))
using (var page = await browser.NewPageAsync())
{
await page.GoToAsync(song.Url);
//请求之后 就是用语法 有就获取src
var jsSelectAllAnchors = @"Array.from(document.querySellectorAll('audio')).map(a=>a.src);";
var urls=await page.EvaluateExpressionAsync<string[]>(jsSelectAllAnchors);
if (urls != null&&urls.Length>0)
{
wc.DownloadFile(urls[0],"./songs/"+song.SongName+".mp3");
}
}
}
遇到的问题 jsSelectAllAnchors 这里面的命令哪里来的 写错了一个单词 找了有点久
细节UI 播放控制台
双击
跑起来了
简单的播放 可以下载播放 下载延迟很耗时间
小编表示 wpf 界面代码写起来 这还是有点底子 ,写起来 比vue webfrom react 都麻烦=.=。。。。。
.net几行代码音乐API各排行榜 热搜 入库-CSDN博客
ABP.Next系列02 搭个API框架要多久 项目下载 运行 -Fstyle_【abp vnext】下载并运行web api项目详细教程文档-CSDN博客