今天感覺好累啊。。還是堅持記錄下。
收集的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()
channel=1 公共兆赫【地區 語言】:華語MHZchannel=6 公共兆赫【地區 語言】:粵語MHZchannel=2 公共兆赫【地區 語言】:歐美MHZchannel=22 公共兆赫【地區 語言】:法語MHZchannel=17 公共兆赫【地區 語言】:日語MHZchannel=18 公共兆赫【地區 語言】:韓語MHZ
channel=3 公共兆赫【年代】:70年代MHZchannel=4 公共兆赫【年代】:80年代MHZchannel=5 公共兆赫【年代】: 90年代MHZ
channel=8 公共兆赫【流派】:民謠MHZchannel=7 公共兆赫【流派】:搖滾MHZchannel=13 公共兆赫【流派】:爵士MHZchannel=27 公共兆赫【流派】:古典MHZchannel=14 公共兆赫【流派】:電子MHZchannel=16 公共兆赫【流派】:R&BMHZchannel=15 公共兆赫【流派】:說唱MHZchannel=10 公共兆赫【流派】:電影原聲MHZ
channel=20 公共兆赫【特輯】:女聲MHZchannel=28 公共兆赫【特輯】:動漫MHZchannel=32 公共兆赫【特輯】:咖啡MHZchannel=67 公共兆赫【特輯】:東京事變MHZ
channel=52 公共兆赫【品牌】:樂混翻唱MHZchannel=58 公共兆赫【品牌】:路虎攬勝運動MHZ
channel=26 公共兆赫:豆瓣音樂人MHZchannel=dj DJ兆赫
其對應的XML
1 <?xml version="1.0" encoding="utf-8"?> 2 <AlreadyKnowChannels> 3 <Channel name="華語MHZ" channelid="1" group="Langurage"></Channel> 4 <Channel name="粵語MHZ" channelid="6" group="Langurage"></Channel> 5 <Channel name="歐美MHZ" channelid="2" group="Langurage"></Channel> 6 <Channel name="法語MHZ" channelid="22" group="Langurage"></Channel> 7 <Channel name="日語MHZ" channelid="17" group="Langurage"></Channel> 8 <Channel name="韓語MHZ" channelid="18" group="Langurage"></Channel> 9 <Channel name="70年代MHZ" channelid="3" group="Ages"></Channel>10 <Channel name="80年代MHZ" channelid="4" group="Ages"></Channel>11 <Channel name="90年代MHZ" channelid="5" group="Ages"></Channel>12 <Channel name="民謠MHZ" channelid="8" group="Genre"></Channel>13 <Channel name="搖滾MHZ" channelid="7" group="Genre"></Channel>14 <Channel name="爵士MHZ" channelid="13" group="Genre"></Channel>15 <Channel name="古典MHZ" channelid="27" group="Genre"></Channel>16 <Channel name="電子MHZ" channelid="14" group="Genre"></Channel>17 <Channel name="RBMHZ" channelid="16" group="Genre"></Channel>18 <Channel name="說唱MHZ" channelid="15" group="Genre"></Channel>19 <Channel name="電影原聲MHZ" channelid="10" group="Genre"></Channel>20 <Channel name="女聲MHZ" channelid="20" group="Special"></Channel>21 <Channel name="動漫MHZ" channelid="28" group="Special"></Channel>22 <Channel name="咖啡MHZ" channelid="32" group="Special"></Channel>23 <Channel name="東京事變MHZ" channelid="67" group="Special"></Channel>24 <Channel name="樂混翻唱MHZ" channelid="52" group="Com"></Channel>25 <Channel name="路虎攬勝運動MHZ" channelid="58" group="Com"></Channel>26 <Channel name="豆瓣音樂人MHZ" channelid="26" group="Artist"></Channel>27 <Channel name="DJ兆赫" channelid="dj" group="Artist"></Channel>28 </AlreadyKnowChannels>
1 XDocument xdoc = XDocument.Load("XML/Channels.xml"); 2 XMLChannels = xdoc.Root.Descendants("Channel").Select( 3 (element) => 4 { 5 return new Channel 6 { 7 name = (string)element.Attribute("name"), 8 channelid = (string)element.Attribute("channelid"), 9 group = (string)element.Attribute("group")10 };11 }).ToList();
再導入, XMLChannels是List<Channe>類型。
接下來創建Model
1 for (int i = 0; i < XMLChannels.Count; i++)2 {3 channels.Add(new 豆瓣電臺.Model.Channel() { ChannelGroup = XMLChannels[i].group, ChannelName = XMLChannels[i].name, ChannelId = XMLChannels[i].channelid });4 }
下面是請求圖片,由于異步關系,我們要把請求的順序編號(就是那個i)也放到get類中去。
再在返回的string中放入末尾。最后就可以從訂閱者里面取出來了。10,11行即是計算編號并去掉末尾這個編號,(這個編號是為了表明請求的頻道ID與我們的頻道表的索引(index)的一一對應的關系)
1 for (int i = 0; i < Channels.Count; i++) 2 { 3 new MyRxGetMethodService().Get("http://douban.fm/j/explore/get_channel_info?cid=" + channels[i].ChannelId, i).ObserveOn(Deployment.Current) 4 .Subscribe( 5 (result) => 6 { 7 8 try 9 {10 int tempcount = int.Parse(result.Substring(result.LastIndexOf("}") + 1, 1));11 result = result.Substring(0, result.LastIndexOf("}") + 1);12 JToken temptoken = JToken.Parse(result)["data"]["res"];13 // BitmapImage bitmap = new BitmapImage();14 // bitmap.UriSource = new Uri(temptoken["cover"].ToString(), UriKind.Absolute);15 var dataitem = channels[tempcount];16 dataitem.ChannelImageSource = new Uri(temptoken["cover"].ToString(), UriKind.Absolute);17 dataitem.ChannelIntro = temptoken["intro"].ToString();18 19 }20 catch21 {22 }23 24 });25 // Thread.Sleep(100);26 }
背后邏輯基本好了,下面是界面
databoundlist的itemtemplate如下:用了一個SlideHubTile,使結果看起來生動一點,SlideHubTile有正面樣式和背面樣式。
1 <DataTemplate x:Key="JumpListItemTemplate"> 2 <Grid > 3 <Grid.Resources> 4 <DataTemplate x:Key="TitleHub"> 5 <Grid> 6 <TextBlock Text="{Binding ChannelName}" Foreground="White"/> 7 </Grid> 8 </DataTemplate> 9 <DataTemplate x:Key="BackHub">10 <Grid Background="#FF0072FF">11 <Image Source="{Binding ChannelImageSource}"12 Stretch="UniformToFill"/>13 <StackPanel Orientation="Vertical">14 <TextBlock Text="{Binding ChannelIntro}" Foreground="White" Height="85.5" Width="150" HorizontalAlignment="Left"/>15 <TextBlock Height="85.5" Text="{Binding ChannelName}" Width="150" HorizontalAlignment="Left" Margin="0" Foreground="#FFE2901B"/>16 </StackPanel>17 </Grid>18 </DataTemplate>19 </Grid.Resources>20 <telerikPRimitives:RadSlideHubTile Title="{Binding}" TitleTemplate="{StaticResource TitleHub}" BackContentTemplate="{StaticResource BackHub}" BackContent="{Binding}" Foreground="#FF1BA1E2">21 <telerikPrimitives:RadSlideHubTile.Picture>22 <Image Source="{Binding ChannelImageSource}"23 Stretch="UniformToFill"/>24 </telerikPrimitives:RadSlideHubTile.Picture>25 </telerikPrimitives:RadSlideHubTile>26 </Grid>27 </DataTemplate>
對于組的顯示樣式,我們可以用原先的模板
1 <helpers:JumpListFirstItemTemplateSelector x:Key="HeaderTemplateSelector"> 2 <helpers:JumpListFirstItemTemplateSelector.FirstItemTemplate> 3 <DataTemplate> 4 <Grid Margin="0,-8,0,12" Width="480"> 5 <TextBlock FontSize="{StaticResource PhoneFontSizeMedium}" Text="{Binding }" TextWrapping="Wrap"/> 6 </Grid> 7 </DataTemplate> 8 </helpers:JumpListFirstItemTemplateSelector.FirstItemTemplate> 9 <helpers:JumpListFirstItemTemplateSelector.StandardItemTemplate>10 <DataTemplate>11 <Grid Margin="0,20,0,12" Width="480">12 <TextBlock FontSize="{StaticResource PhoneFontSizeMedium}" Text="{Binding }" TextWrapping="Wrap"/>13 </Grid>14 </DataTemplate>15 </helpers:JumpListFirstItemTemplateSelector.StandardItemTemplate>16 </helpers:JumpListFirstItemTemplateSelector>
最后是DataBoundList的XAML
1 <telerikData:RadJumpList Margin="18,56,18,-44" 2 GroupDescriptorssource="{Binding ChannelGroupDescriptors}" 3 ItemsSource="{Binding Channels}" 4 ItemTemplate="{StaticResource JumpListItemTemplate}" 5 GroupHeaderTemplateSelector="{StaticResource HeaderTemplateSelector}" 6 x:Name="jumplist" 7 > 8 <telerikData:RadJumpList.VirtualizationStrategyDefinition> 9 <telerikPrimitives:WrapVirtualizationStrategyDefinition Orientation="Horizontal"/>10 </telerikData:RadJumpList.VirtualizationStrategyDefinition>11 <i:Interaction.Triggers>12 <i:EventTrigger EventName="ItemTap">13 <GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding ShowChannleDetials, Mode=OneWay}" PassEventArgsToCommand="True"/>14 </i:EventTrigger>15 </i:Interaction.Triggers>16 </telerikData:RadJumpList>
用Command把點選的頻道傳到VM中去。
效果大致如下,(有些圖片出不來,有點沒弄明白)
借用前段時間看DEEPDIVEMVVM中學到的,注入一個導航接口,
思路大致就是那個視頻中提到的思路,也有源碼下載。
1 public RelayCommand<Telerik.Windows.Controls.ListBoxItemTapEventArgs> ShowChannleDetials 2 { 3 get 4 { 5 return showchanneldetials 6 ?? (showchanneldetials = new RelayCommand<Telerik.Windows.Controls.ListBoxItemTapEventArgs>( 7 (args) => 8 { 9 Channel item = (args.Item.Content) as Channel;10 string key = item.ChannelId;11 new MyRxGetMethodService().Get("http://douban.fm/j/mine/playlist?type=n&channel=" + item.ChannelId + "&pb=64&from=mainsite").ObserveOn(Deployment.Current).Subscribe(12 (result) =>13 {14 var songs_string = JToken.Parse(result)["song"].ToString();15 var MySongs = JsonConvert.DeserializeObject<List<Song>>(songs_string);16 if (!SimpleIoc.Default.IsRegistered<ChannelDetailViewModel>(key))17 {18 SimpleIoc.Default.Register<ChannelDetailViewModel>(19 () =>20 {21 var mainvm = new ChannelDetailViewModel(MySongs,item.ChannelName,item.ChannelIntro,item.ChannelId,item.ChannelImageSource);22 23 return mainvm;24 }, key);25 }26 _navigate.NavigateTo(27 new Uri(28 "/ChannelDetail.xaml?" + key,29 UriKind.Relative));30 31 });32 33 }));34 }35 }
注意new的ChannelDetailViewModel時候注入參數,還有在Ioc中注冊
View部分直接使用Telerik的模板:最后效果如下:
要注意在View中也有部分代碼:
別忘了在退出這個頁面的時候取消掉VM的注冊(再點擊的過程中會重復注冊)
1 public partial class ChannelDetail : PhoneapplicationPage 2 { 3 private string itemUrl; 4 public ChannelDetail() 5 { 6 InitializeComponent(); 7 } 8 protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) 9 {10 if (DataContext == null)11 {12 var url = e.Uri.ToString();13 itemUrl = url.Substring(url.IndexOf("?") + 1);14 15 if (!SimpleIoc.Default.IsRegistered<ChannelDetailViewModel>(itemUrl))16 {17 MessageBox.Show("Item not found");18 return;19 }20 21 var vm = SimpleIoc.Default.GetInstance<ChannelDetailViewModel>(itemUrl);22 23 DataContext = vm;24 }25 base.OnNavigatedTo(e);26 }27 protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)28 {29 if (SimpleIoc.Default.IsRegistered<ChannelDetailViewModel>(itemUrl))30 {31 SimpleIoc.Default.Unregister<ChannelDetailViewModel > (itemUrl);32 }33 base.OnNavigatingFrom(e);34 }35 private void Option1_Tap(object sender, System.Windows.Input.GestureEventArgs e)36 {37 this.Option1Viewer.Visibility = System.Windows.Visibility.Visible;38 this.Option1Arrow.Visibility = System.Windows.Visibility.Visible;39 this.Option2Viewer.Visibility = System.Windows.Visibility.Collapsed;40 this.Option2Arrow.Visibility = System.Windows.Visibility.Collapsed;41 }42 43 private void Option2_Tap(object sender, System.Windows.Input.GestureEventArgs e)44 {45 this.Option1Viewer.Visibility = System.Windows.Visibility.Collapsed;46 this.Option1Arrow.Visibility = System.Windows.Visibility.Collapsed;47 this.Option2Viewer.Visibility = System.Windows.Visibility.Visible;48 this.Option2Arrow.Visibility = System.Windows.Visibility.Visible;49 }50 }
還有點擊圖片更新歌曲:
使Songs重新指向一片區域,再raise屬性改變,最后效果如下:
1 public RelayCommand RefreshCommand 2 { 3 get 4 { 5 return refreshcommand 6 ?? (refreshcommand = new RelayCommand( 7 () => 8 { 9 new MyRxGetMethodService().Get("http://douban.fm/j/mine/playlist?type=n&channel=" + ChannelId + "&pb=64&from=mainsite").ObserveOn(Deployment.Current).Subscribe(10 (result) =>11 {12 var songs_string = JToken.Parse(result)["song"].ToString();13 var Songs3 = JsonConvert.DeserializeObject<List<Song>>(songs_string);14 Song[] tempsongs = new Song[songs.Count];15 songs.CopyTo(tempsongs);16 List<Song> songstemp1 = new List<Song>(tempsongs);17 songstemp1.AddRange(Songs3);18 Songs = songstemp1;19 });20 }));21 }22 }
還有些想法還沒實現,今天就到這里吧
新聞熱點
疑難解答