不得不说listPicker是个有用但是很操蛋的控件,对于我这种完全不懂数据绑定的新手来说尤其操蛋。
我要实现这样一个功能:在一个设置页面放置一个listPicker控件,用于选择颜色,其中ExpansionMode="FullScreenOnly",就是点击会全屏展开的那种。用户做出选择后,根据用户所选颜色做相应的响应事件,然后将选择结果保存。
在.xaml里面增加一个listPicker,代码如下:
1 <toolkit: ListPicker x: Name="ChoseAccentColor" ItemsSource ="{Binding}" Header="{Binding Path =LocalizedResources.Setting_color, Source={ StaticResource LocalizedStrings}}" FullModeHeader="{ Binding Path=LocalizedResources.Setting_fullmodecolor, Source={StaticResource LocalizedStrings}}" ExpansionMode="FullScreenOnly" SelectionChanged="ChoseAccentColor_SelectionChanged" Margin ="0" Width="422"> 2 <toolkit: ListPicker.FullModeItemTemplate> 3 <DataTemplate> 4 <toolkit: WrapPanel> 5 <Rectangle Fill ="{Binding}" Width="60" Height ="60" Margin="10" /> 6 <TextBlock Text ="{Binding}" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize ="32" Margin="10"/> 7 </toolkit: WrapPanel> 8 </DataTemplate> 9 </toolkit: ListPicker.FullModeItemTemplate> 10 <toolkit: ListPicker.ItemTemplate> 11 <DataTemplate> 12 <StackPanel Orientation ="Horizontal"> 13 <Rectangle Fill ="{Binding}" Width="20" Height ="20" /> 14 <TextBlock Text ="{Binding}" VerticalAlignment="Center" Margin="10, 0, 0, 0"/> 15 </StackPanel> 16 </DataTemplate> 17 </toolkit: ListPicker.ItemTemplate> 18 </toolkit: ListPicker>
然后在.cs中进行数据绑定:
1 this.ChoseAccentColor.ItemsSource = new List< string>() { "Lime" , "Green" , "Teal" , "Cyan" , "Indigo" , "Violet" , "Pink" , "Magenta" , "Crimson" , "Red" , "Orange" , "Yellow" , "Brown" , "Olive" , "Sienna" };
然后问题就来了,只要listPicker控件所在页面被初始化,listPicker的SelectionChanged事件就被执行,而且是执行两次:首次加载执行一次,然后绑定数据源的时候执行一次。我用的Visual Studio 2013RC,有人说是环境的问题,也有人说是新版toolkit才有的问题,旧版本没有,这个问题我们不讨论...
我众里寻他千百度,就是木有看到“答案”在灯火阑珊处。唯一比较接近我问题答案的http://bbs.csdn.net/topics/390446549
算了,先不管它了,先用独立存储把我用户选择的结果保存起来吧,于是惯性思维,写了如下代码:
1 protected override void OnNavigatedTo(NavigationEventArgs e) 2 { 3 base.OnNavigatedTo(e); 4 5 if (settings.Contains("Color" )) 6 { 7 this.ChoseAccentColor.SelectedIndex= (int)settings[ "Color"]; 8 } 9 } 10 11 protected override void OnNavigatedFrom(NavigationEventArgs e) 12 { 13 settings[ "Color"] = this .ChoseAccentColor.SelectedIndex; 14 15 settings.Save(); 16 base.OnNavigatedFrom(e); 17 }
一运行,发现不但不能像往常一样正常的存取值,连litsPicker控件那个框里面的值都无法修改,无论怎么选择,那个值都只显示默认的第一行的值。在VS里面debug了一下,发现了问题所在:
1.第一次点击listpicker,执行OnNavigatedFrom,会将this.ChoseAccentColor.SelectedIndex=0的值送给settings["Color"]
![](http://images0.cnblogs.com/blog/571875/201310/07021836-45565a13973d46afb5030330c8f34b5b.jpg)
![](http://images0.cnblogs.com/blog/571875/201310/07022001-5343f055356f4658a7150000970e964a.jpg)
2.此时页面跳转至listpicker的全屏界面
![](http://images0.cnblogs.com/blog/571875/201310/07022155-f4c61b095fa34a10ba3ee10897ae3e4f.jpg)
选中一项之后selsetedindex的值暂时变成5
![](http://images0.cnblogs.com/blog/571875/201310/07022241-6cb7c967c7a54f35af3649d4da649ab6.jpg)
3.执行OnNavigatedTo,selectedindex的值再次被setting【“color”】修改成0
![](http://images0.cnblogs.com/blog/571875/201310/07022322-2330eaa8c80f40168c583e17bb3382fb.jpg)
由于listPicker的两次自发的导航使得我那样的做法根本无法存值,节操碎了一地有木有。然后又是各种问,各种查,然后【WindowsPhone开发技术交流QQ群157153754】中有人提供了一种思路:
重写OnBackKeyPress方法,在这个里面存的用户设置。就是说,当用户点击返回按键的时候才会存储设置。试了一下,感觉OK。
后来无聊中翻到了微软的windows phone8开发视频教程,里面有一集专门讲解“应用中的设置文件与存储”的【http://msdn.microsoft.com/zh-cn/dn167659】,还附了demo的下载地址。我down下来跑了一下,果然是我想要的效果。
我照着敲了一遍,适当的根据我app的要求修改了一些,然后运行通过。但是我依旧不是很懂这样做的道理,也不清楚这到底是不是某大神所说的“绑定”。
新增一个ColorSettingHelper类,在这里面写SaveColorSetting()和LoadColorSetting()方法,由于我要做的是根据选择,动态的修改tile的背景色,于是增加一个changeIconicTileBackgroundColor()方法
代码如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.IO.IsolatedStorage; 7 using Microsoft.Phone.Shell; 8 using System.Windows.Media; 9 10 namespace Flashlight.Helper 11 { 12 class ColorSettingHelper 13 { 14 /// <summary> 15 /// Save data of color to the local. 16 /// </summary> 17 /// <param name="data"></param> 18 public void SaveColorSetting(string data) 19 { 20 var localColorSetting = IsolatedStorageSettings.ApplicationSettings; 21 localColorSetting["Color"] = data; 22 } 23 24 /// <summary> 25 /// Read the local data of color. 26 /// </summary> 27 /// <returns></returns> 28 public string LoadColorSetting() 29 { 30 var localColorSetting = IsolatedStorageSettings.ApplicationSettings; 31 var result = localColorSetting.Where(a => a.Key == "Color"); 32 33 if (result.Any()) 34 { 35 var color = localColorSetting["Color"].ToString(); 36 return color; 37 } 38 return "PhoneAccentBrush"; 39 } 40 41 /// <summary> 42 /// Modify accent color of tile. 43 /// </summary> 44 /// <param name="color"></param> 45 public void ModifyTileAccent(string color) 46 { 47 byte r = 0; 48 byte g = 0; 49 byte b = 0; 50 51 switch (color) 52 { 53 case "Lime": 54 r = 164; 55 g = 196; 56 b = 0; 57 break; 58 case "Green": 59 r = 96; 60 g = 169; 61 b = 23; 62 break; 63 case "Teal": 64 r = 0; 65 g = 171; 66 b = 169; 67 break; 68 case "Cyan": 69 r = 27; 70 g = 161; 71 b = 226; 72 break; 73 case "Indigo": 74 r = 106; 75 g = 0; 76 b = 255; 77 break; 78 case "Violet": 79 r = 170; 80 g = 0; 81 b = 255; 82 break; 83 case "Pink": 84 r = 244; 85 g = 114; 86 b = 208; 87 break; 88 case "Magenta": 89 r = 216; 90 g = 0; 91 b = 115; 92 break; 93 case "Crimson": 94 r = 162; 95 g = 0; 96 b = 37; 97 break; 98 case "Red": 99 r = 229; 100 g = 20; 101 b = 0; 102 break; 103 case "Orange": 104 r = 250; 105 g = 104; 106 b = 0; 107 break; 108 case "Yellow": 109 r = 216; 110 g = 193; 111 b = 0; 112 break; 113 case "Brown": 114 r = 130; 115 g = 90; 116 b = 44; 117 break; 118 case "Olive": 119 r = 109; 120 g = 135; 121 b = 100; 122 break; 123 case "Sienna": 124 r = 122; 125 g = 59; 126 b = 63; 127 break; 128 default: 129 break; 130 } 131 132 changeIconicTileBackgroundColor(r, g, b); 133 } 134 135 /// <summary> 136 /// Change IconicTile BackgroundColor 137 /// </summary> 138 /// <param name="r"></param> 139 /// <param name="g"></param> 140 /// <param name="b"></param> 141 private void changeIconicTileBackgroundColor(byte r, byte g, byte b) 142 { 143 ShellTile tileToFind = ShellTile.ActiveTiles.First(); 144 145 if (tileToFind != null) 146 { 147 IconicTileData TileData = new IconicTileData() 148 { 149 //Title = AppResources.ApplicationTitle, 150 IconImage = new Uri("/Assets/Tiles/IconicTileMediumLarge.png", UriKind.Relative), 151 BackgroundColor = new Color { A = 255, R = r, G = g, B = b } 152 }; 153 tileToFind.Update(TileData); 154 } 155 } 156 } 157 }
然后回到设置页面,在SelectionChanged事件中获取到用户的选择,并保存设置,然后在OnNavigatedTo和App.xaml.cs的Application_Launching中加载设置
代码如下:
1 private void ChoseAccentColor_SelectionChanged( object sender, SelectionChangedEventArgs e) 2 { 3 var listPicker = sender as ListPicker ; 4 var selectIndex = listPicker.SelectedIndex; 5 6 if (selectIndex != 0) 7 { 8 var color = listPicker.SelectedItem as string; 9 var manager = new Flashlight.Helper. ColorSettingHelper (); 10 11 manager.ModifyTileAccent(color); 12 manager.SaveColorSetting(color); 13 } 14 } 15 16 protected override void OnNavigatedTo( NavigationEventArgs e) 17 { 18 base.OnNavigatedTo(e); 19 20 var color = new Flashlight.Helper.ColorSettingHelper ().LoadColorSetting(); 21 22 for ( int i = 0; i < this.ChoseAccentColor.Items.Count; i++) 23 { 24 if ( this.ChoseAccentColor.Items[i].ToString() == color) 25 { 26 this.ChoseAccentColor.SelectedIndex = i; 27 } 28 } 29 }
注:ColorSettingHelper 类是放在一个Helper文件夹中的
这样就万事大吉了。
转载请注明住处:http://www.cnblogs.com/aerodynamics/