今天感觉好累啊。。还是坚持记录下。
收集的API:
https://github.com/HakurouKen/douban.fm-api
https://github.com/zonyitoo/doubanfm-qt/wiki/%E8%B1%86%E7%93%A3FM-API
https://github.com/ampm/douban-fm-sdk
都没有提到Cookie
利用这个API,本来想弄下COOKie的但是Post请求老是通过不过,索性作罢
记录下频道部分的搭建
根据下面的已知分组情况,想到用xml保存下来,再用分组的控件比较好。
想到像Toolkit的longlist(具体名字我忘了)在telerik的控件下,有一个更加方便使用的,叫RadDataBoundListBox,非常好用,分起组来很简单。
首先老样子,先绑定一个DataContext,新建VM类,Ioc注册等等。
一:频道表:已知固定频道channel=0 私人兆赫 type=e()
Region&Langchannel=1 公共兆赫【地区 语言】:华语MHZ
channel=6 公共兆赫【地区 语言】:粤语MHZ
channel=2 公共兆赫【地区 语言】:欧美MHZ
channel=22 公共兆赫【地区 语言】:法语MHZ
channel=17 公共兆赫【地区 语言】:日语MHZ
channel=18 公共兆赫【地区 语言】:韩语MHZ
Ageschannel=3 公共兆赫【年代】:70年代MHZ
channel=4 公共兆赫【年代】:80年代MHZ
channel=5 公共兆赫【年代】: 90年代MHZ
Genrechannel=8 公共兆赫【流派】:民谣MHZ
channel=7 公共兆赫【流派】:摇滚MHZ
channel=13 公共兆赫【流派】:爵士MHZ
channel=27 公共兆赫【流派】:古典MHZ
channel=14 公共兆赫【流派】:电子MHZ
channel=16 公共兆赫【流派】:R&BMHZ
channel=15 公共兆赫【流派】:说唱MHZ
channel=10 公共兆赫【流派】:电影原声MHZ
Specialchannel=20 公共兆赫【特辑】:女声MHZ
channel=28 公共兆赫【特辑】:动漫MHZ
channel=32 公共兆赫【特辑】:咖啡MHZ
channel=67 公共兆赫【特辑】:东京事变MHZ
Comchannel=52 公共兆赫【品牌】:乐混翻唱MHZ
channel=58 公共兆赫【品牌】:路虎揽胜运动MHZ
Artistchannel=26 公共兆赫:豆瓣音乐人MHZ
channel=dj DJ兆赫
其对应的XML
1<?xml version="1.0" encoding="utf-8"?>2<AlreadyKnowChannels>3<Channelname="华语MHZ"channelid="1"group="Langurage"></Channel>4<Channelname="粤语MHZ"channelid="6"group="Langurage"></Channel>5<Channelname="欧美MHZ"channelid="2"group="Langurage"></Channel>6<Channelname="法语MHZ"channelid="22"group="Langurage"></Channel>7<Channelname="日语MHZ"channelid="17"group="Langurage"></Channel>8<Channelname="韩语MHZ"channelid="18"group="Langurage"></Channel>9<Channelname="70年代MHZ"channelid="3"group="Ages"></Channel>10<Channelname="80年代MHZ"channelid="4"group="Ages"></Channel>11<Channelname="90年代MHZ"channelid="5"group="Ages"></Channel>12<Channelname="民谣MHZ"channelid="8"group="Genre"></Channel>13<Channelname="摇滚MHZ"channelid="7"group="Genre"></Channel>14<Channelname="爵士MHZ"channelid="13"group="Genre"></Channel>15<Channelname="古典MHZ"channelid="27"group="Genre"></Channel>16<Channelname="电子MHZ"channelid="14"group="Genre"></Channel>17<Channelname="RBMHZ"channelid="16"group="Genre"></Channel>18<Channelname="说唱MHZ"channelid="15"group="Genre"></Channel>19<Channelname="电影原声MHZ"channelid="10"group="Genre"></Channel>20<Channelname="女声MHZ"channelid="20"group="Special"></Channel>21<Channelname="动漫MHZ"channelid="28"group="Special"></Channel>22<Channelname="咖啡MHZ"channelid="32"group="Special"></Channel>23<Channelname="东京事变MHZ"channelid="67"group="Special"></Channel>24<Channelname="乐混翻唱MHZ"channelid="52"group="Com"></Channel>25<Channelname="路虎揽胜运动MHZ"channelid="58"group="Com"></Channel>26<Channelname="豆瓣音乐人MHZ"channelid="26"group="Artist"></Channel>27<Channelname="DJ兆赫"channelid="dj"group="Artist"></Channel>28</AlreadyKnowChannels>
1XDocument xdoc = XDocument.Load("XML/Channels.xml");2XMLChannels = xdoc.Root.Descendants("Channel").Select(3(element) =>4{5returnnewChannel6{7name = (string)element.Attribute("name"),8channelid = (string)element.Attribute("channelid"),9group = (string)element.Attribute("group")10};11}).ToList();
再导入, XMLChannels是List<Channe>类型。
接下来创建Model
1for(inti =0; i < XMLChannels.Count; i++)2{3channels.Add(new豆瓣电台.Model.Channel() { ChannelGroup = XMLChannels[i].group, ChannelName = XMLChannels[i].name, ChannelId =XMLChannels[i].channelid });4}
下面是请求图片,由于异步关系,我们要把请求的顺序编号(就是那个i)也放到get类中去。
再在返回的string中放入末尾。最后就可以从订阅者里面取出来了。10,11行即是计算编号并去掉末尾这个编号,(这个编号是为了表明请求的频道ID与我们的频道表的索引(index)的一一对应的关系)
1for(inti =0; i < Channels.Count; i++)2{3newMyRxGetMethodService().Get("http://douban.fm/j/explore/get_channel_info?cid="+channels[i].ChannelId, i).ObserveOn(Deployment.Current)4.Subscribe(5(result) =>6{78try9{10inttempcount =int.Parse(result.Substring(result.LastIndexOf("}") +1,1));11result = result.Substring(0, result.LastIndexOf("}") +1);12JToken temptoken = JToken.Parse(result)["data"]["res"];13//BitmapImage bitmap = new BitmapImage();14//bitmap.UriSource = new Uri(temptoken["cover"].ToString(), UriKind.Absolute);15vardataitem =channels[tempcount];16dataitem.ChannelImageSource =newUri(temptoken["cover"].ToString(), UriKind.Absolute);17dataitem.ChannelIntro = temptoken["intro"].ToString();1819}20catch21{22}2324});25//Thread.Sleep(100);26}
背后逻辑基本好了,下面是界面
databoundlist的itemtemplate如下:用了一个SlideHubTile,使结果看起来生动一点,SlideHubTile有正面样式和背面样式。
1<DataTemplatex:Key="JumpListItemTemplate">2<Grid>3<Grid.Resources>4<DataTemplatex:Key="TitleHub">5<Grid>6<TextBlockText="{Binding ChannelName}"Foreground="White"/>7</Grid>8</DataTemplate>9<DataTemplatex:Key="BackHub">10<GridBackground="#FF0072FF">11<ImageSource="{Binding ChannelImageSource}"12Stretch="UniformToFill"/>13<StackPanelOrientation="Vertical">14<TextBlockText="{Binding ChannelIntro}"Foreground="White"Height="85.5"Width="150"HorizontalAlignment="Left"/>15<TextBlockHeight="85.5"Text="{Binding ChannelName}"Width="150"HorizontalAlignment="Left"Margin="0"Foreground="#FFE2901B"/>16</StackPanel>17</Grid>18</DataTemplate>19</Grid.Resources>20<telerikPRimitives:RadSlideHubTileTitle="{Binding}"TitleTemplate="{StaticResource TitleHub}"BackContentTemplate="{StaticResource BackHub}"BackContent="{Binding}"Foreground="#FF1BA1E2">21<telerikPrimitives:RadSlideHubTile.Picture>22<ImageSource="{Binding ChannelImageSource}"23Stretch="UniformToFill"/>24</telerikPrimitives:RadSlideHubTile.Picture>25</telerikPrimitives:RadSlideHubTile>26</Grid>27</DataTemplate>
对于组的显示样式,我们可以用原先的模板
1<helpers:JumpListFirstItemTemplateSelectorx:Key="HeaderTemplateSelector">2<helpers:JumpListFirstItemTemplateSelector.FirstItemTemplate>3<DataTemplate>4<GridMargin="0,-8,0,12"Width="480">5<TextBlockFontSize="{StaticResource PhoneFontSizeMedium}"Text="{Binding }"TextWrapping="Wrap"/>6</Grid>7</DataTemplate>8</helpers:JumpListFirstItemTemplateSelector.FirstItemTemplate>9<helpers:JumpListFirstItemTemplateSelector.StandardItemTemplate>10<DataTemplate>11<GridMargin="0,20,0,12"Width="480">12<TextBlockFontSize="{StaticResource PhoneFontSizeMedium}"Text="{Binding }"TextWrapping="Wrap"/>13</Grid>14</DataTemplate>15</helpers:JumpListFirstItemTemplateSelector.StandardItemTemplate>16</helpers:JumpListFirstItemTemplateSelector>
最后是DataBoundList的XAML
1<telerikData:RadJumpListMargin="18,56,18,-44"2GroupDescriptorssource="{Binding ChannelGroupDescriptors}"3ItemsSource="{Binding Channels}"4ItemTemplate="{StaticResource JumpListItemTemplate}"5GroupHeaderTemplateSelector="{StaticResource HeaderTemplateSelector}"6x:Name="jumplist"7>8<telerikData:RadJumpList.VirtualizationStrategyDefinition>9<telerikPrimitives:WrapVirtualizationStrategyDefinitionOrientation="Horizontal"/>10</telerikData:RadJumpList.VirtualizationStrategyDefinition>11<i:Interaction.Triggers>12<i:EventTriggerEventName="ItemTap">13<GalaSoft_MvvmLight_Command:EventToCommandCommand="{Binding ShowChannleDetials, Mode=OneWay}"PassEventArgsToCommand="True"/>14</i:EventTrigger>15</i:Interaction.Triggers>16</telerikData:RadJumpList>
用Command把点选的频道传到VM中去。
效果大致如下,(有些图片出不来,有点没弄明白)
二:具体频道信息借用前段时间看DEEPDIVEMVVM中学到的,注入一个导航接口,
思路大致就是那个视频中提到的思路,也有源码下载。
1publicRelayCommand<Telerik.Windows.Controls.ListBoxItemTapEventArgs>ShowChannleDetials2{3get4{5returnshowchanneldetials6?? (showchanneldetials =newRelayCommand<Telerik.Windows.Controls.ListBoxItemTapEventArgs>(7(args) =>8{9Channel item = (args.Item.Content)asChannel;10stringkey =item.ChannelId;11newMyRxGetMethodService().Get("http://douban.fm/j/mine/playlist?type=n&channel="+ item.ChannelId +"&pb=64&from=mainsite").ObserveOn(Deployment.Current).Subscribe(12(result) =>13{14varsongs_string = JToken.Parse(result)["song"].ToString();15varMySongs = JsonConvert.DeserializeObject<List<Song>>(songs_string);16if(!SimpleIoc.Default.IsRegistered<ChannelDetailViewModel>(key))17{18SimpleIoc.Default.Register<ChannelDetailViewModel>(19() =>20{21varmainvm =newChannelDetailViewModel(MySongs,item.ChannelName,item.ChannelIntro,item.ChannelId,item.ChannelImageSource);2223returnmainvm;24}, key);25}26_navigate.NavigateTo(27newUri(28"/ChannelDetail.xaml?"+key,29UriKind.Relative));3031});3233}));34}35}
注意new的ChannelDetailViewModel时候注入参数,还有在Ioc中注册
View部分直接使用Telerik的模板:最后效果如下:
要注意在View中也有部分代码:
别忘了在退出这个页面的时候取消掉VM的注册(再点击的过程中会重复注册)
1publicpartialclassChannelDetail : PhoneapplicationPage2{3privatestringitemUrl;4publicChannelDetail()5{6InitializeComponent();7}8protectedoverridevoidOnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)9{10if(DataContext ==null)11{12varurl =e.Uri.ToString();13itemUrl = url.Substring(url.IndexOf("?") +1);1415if(!SimpleIoc.Default.IsRegistered<ChannelDetailViewModel>(itemUrl))16{17MessageBox.Show("Item not found");18return;19}2021varvm = SimpleIoc.Default.GetInstance<ChannelDetailViewModel>(itemUrl);2223DataContext =vm;24}25base.OnNavigatedTo(e);26}27protectedoverridevoidOnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)28{29if(SimpleIoc.Default.IsRegistered<ChannelDetailViewModel>(itemUrl))30{31SimpleIoc.Default.Unregister<ChannelDetailViewModel >(itemUrl);32}33base.OnNavigatingFrom(e);34}35privatevoidOption1_Tap(objectsender, System.Windows.Input.GestureEventArgs e)36{37this.Option1Viewer.Visibility =System.Windows.Visibility.Visible;38this.Option1Arrow.Visibility =System.Windows.Visibility.Visible;39this.Option2Viewer.Visibility =System.Windows.Visibility.Collapsed;40this.Option2Arrow.Visibility =System.Windows.Visibility.Collapsed;41}4243privatevoidOption2_Tap(objectsender, System.Windows.Input.GestureEventArgs e)44{45this.Option1Viewer.Visibility =System.Windows.Visibility.Collapsed;46this.Option1Arrow.Visibility =System.Windows.Visibility.Collapsed;47this.Option2Viewer.Visibility =System.Windows.Visibility.Visible;48this.Option2Arrow.Visibility =System.Windows.Visibility.Visible;49}50}
还有点击图片更新歌曲:
使Songs重新指向一片区域,再raise属性改变,最后效果如下:
1publicRelayCommand RefreshCommand2{3get4{5returnrefreshcommand6?? (refreshcommand =newRelayCommand(7() =>8{9newMyRxGetMethodService().Get("http://douban.fm/j/mine/playlist?type=n&channel="+ ChannelId +"&pb=64&from=mainsite").ObserveOn(Deployment.Current).Subscribe(10(result) =>11{12varsongs_string = JToken.Parse(result)["song"].ToString();13varSongs3 = JsonConvert.DeserializeObject<List<Song>>(songs_string);14Song[] tempsongs =newSong[songs.Count];15songs.CopyTo(tempsongs);16List<Song> songstemp1 =newList<Song>(tempsongs);17songstemp1.AddRange(Songs3);18Songs =songstemp1;19});20}));21}22}
三.结语还有些想法还没实现,今天就到这里吧