Windows Phone 7(WP7)开发 AutoCompletedBox制作中文城市名称输入框

Toolkit里的AutoCompletedBox默认的功能已经很强大了,做一个英文城市或者英文单词的提示,可以直接指定FilterMode为AutoCompleteFilterMode.SartsWith(或者其它更合适的过滤器)。

对于自带的FilterMode,请参见MSDN:http://msdn.microsoft.com/zh-cn/library/system.windows.controls.autocompletefiltermode(VS.95).aspx

但是对于中文城市名称过滤来说,恐怕还需要进一步修改。原因如下,由于我们的用户使用的输入可能是中文键盘,举一个很简单的例子来说:用户想找“北京”的时候,他输入[beijing,bei,b,北]都是需要提示的,注意,最后那个是中文,这个时候,就需要亲手来写一些代码啦。

先上个效果图:

首先是Model类

 public class CityModel:BaseModel
{
private string _cityName = "";
private string _pinyin = "";
public string CityName
{
get { return _cityName; }
set
{
_cityName = value;
OnNotifyPropertyChanged("CityName");
}
}
public string Pinyin
{
get { return _pinyin; }
set { _pinyin = value; }
}
}

Model类很简单,就2个属性,CityName为中文名称,Pinyin(嗯,确实是拼音……)为城市的拼音名。

为了实现上图中Items的显示效果,我们需要对其模版进行修改,具体XAML如下:

<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="AutoItemTemplate">
<Grid Width="400" Height="50">
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding CityName}" d:LayoutOverrides="Height"/>
<TextBlock HorizontalAlignment="Left" Margin="200,0,57,8" TextWrapping="Wrap" Text="{Binding Pinyin}" d:LayoutOverrides="Height"/>
</Grid>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
<toolkit:AutoCompleteBox x:Name="TxtUserInput" Margin="0,8,0,0" ItemTemplate="{StaticResource AutoItemTemplate}" ValueMemberPath="CityName" Height="73" VerticalAlignment="Top" />

上面的XAML代码中唯一需要说明的就是AutoCompleteBox的ValueMemberPath属性,由于Item的数据源是CityModel类型的,如上图,这时如果用户点击“北京    beijing”这个项目时,在文本框中是显示"北京"或者"beijing"就取决于ValueMemberPath的设置了。

在XAML的CS页面里,需要进一步指定AutoCompleteBox的数据源(抱歉没有严格使用MVVM绑定,这不是重点。。)

private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
viewModel = new InputCityNameViewModel();
this.DataContext = viewModel;
TxtUserInput.ItemsSource = viewModel.ListCities;
TxtUserInput.FilterMode = AutoCompleteFilterMode.Custom;
TxtUserInput.ItemFilter = viewModel.Filter;
TxtUserInput.Focus();
}
ViewModel里的一些内容:
public class InputCityNameViewModel : BaseViewModel
{
public IList<CityModel> ListCities = new List<CityModel>();
public InputCityNameViewModel()
{
LoadCities();
}
private void LoadCities()
{
//读取城市信息
}
public bool Filter(string strInput, object toFilter)
{
CityModel model = (CityModel)toFilter;
if (model.Pinyin.StartsWith(strInput) || model.CityName.StartsWith(strInput))
return true;
else
{
return false;
}
}
}

这里的关键就是Filter了,代码很简单,很容易看懂。

顺便再谈一个Bug的问题,AutoCompleteBox在Pivot里面的提示显示是不正常的,而且显示和触控是错位的,网上有大牛给出了变相的解决办法,但我一直认为那太复杂,个人比较懒。。前两天Bing了一下,突然眼前一亮,截图纪念一下:


粗略看了摘要之后(确实是粗略,因为中间有”…”我也没太注意),我当时以为随着Toolkit的新版的发布,这个问题已经解决了,但是点击进去一看,发现“Toolkit新版发布”和“AutoCompleteBox在Pivot的Bug的解决”这完全是两篇不同的文章…… 彻底崩溃。。

但是必须要在Pivot里面让用户输入城市名字的,这个怎么办。后来直接用了个笨点的办法,我把Pivot里面的AutoCompleteBox换成了TextBox,然后当Text获得焦点之后,跳转到一个新页面,空白页面上只有AutoCompleteBox,当用户输入完成之后再把值传递回去,算是个障眼法么。。不过我记得有很多时候在手机上都是这么做的——当用户点击输入框之后屏幕上只显示输入框和键盘及候选字,输入完之后再返回去。这样用户体验也不会太差,总比在Pivot上面硬生生的让用户直面Bug来得好,这也算是一个临时的解决办法吧,期待Toolkit的升级~

原文地址:https://www.cnblogs.com/vistach/p/Windows_Phone_WP7_AutoCompleteBox_Item_Filter_Pivot.html