本文中所有代码都可以在github中查看,git版本中采用了master-dev的方式。在master中可以查看每一个demo的最后完成,在dev中可以查看每一步的代码。
github地址:[email protected]:kiwiwin/silverlight-demo.git。文件夹名称autocomplete-custom-searchmode-demo
1、AutoCompleteBox自定义数据Person
Person的定义:
public class Person { public String FirstName { get; set; } public String SecondName { get; set; } }
定义AutoCompleteBox:
<sdk:AutoCompleteBox Height="28" HorizontalAlignment="Center" x:Name="wordAutoCompleteBox" VerticalAlignment="Center" Width="200" />
初始化静态数据:
public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); wordAutoCompleteBox.ItemsSource = Persons(); } private IEnumerable<Person> Persons() { var persons = new List<Person>(); persons.Add(new Person {FirstName = "java", SecondName = "china"}); persons.Add(new Person {FirstName = "csharp", SecondName = "japan"}); persons.Add(new Person {FirstName = "cplusplus", SecondName = "india"}); persons.Add(new Person {FirstName = "ruby", SecondName = "china"}); persons.Add(new Person {FirstName = "python", SecondName = "korea"}); return persons; } }
此时启动,在AutoCompleteBox中输入c不会有提示,这是因为AutoCompleteBox不知道如何显示,也不知道如何匹配:
定义Person的AutoCompleteBox中提示的显示方式,使用ItemTemplate。
<StackPanel x:Name="LayoutRoot" Background="White"> <sdk:AutoCompleteBox Height="28" HorizontalAlignment="Center" x:Name="wordAutoCompleteBox" VerticalAlignment="Center" Width="200" > <sdk:AutoCompleteBox.ItemTemplate> <DataTemplate> <Grid Width="200"> <Grid.ColumnDefinitions> <ColumnDefinition Width="100"></ColumnDefinition> <ColumnDefinition Width="100"></ColumnDefinition> </Grid.ColumnDefinitions> <TextBlock HorizontalAlignment="Left" Foreground="Gray" Text="{Binding FirstName}" Grid.Column="0"/> <TextBlock HorizontalAlignment="Left" Foreground="Gray" Text="{Binding SecondName}" Grid.Column="1"/> </Grid> </DataTemplate> </sdk:AutoCompleteBox.ItemTemplate> </sdk:AutoCompleteBox>
自定义匹配规则是FirstName中含有已在AutoCompleteBox中输入的字符:
wordAutoCompleteBox.ItemFilter = (search, item) => { Person person = item as Person; if (person != null) { return person.FirstName.Contains(search); } return false; };
此时,能够给出提示了,但是当选中其中某一个提示时,AutoCompleteBox显示的字符串变成了”autocomplete_custom_searchmode_demo.Person“。可以推测,这是因为Person缺少了ToString函数。
public override String ToString() { return FirstName + " " + SecondName; }
添上以后,可以进行正确提示了。如下图
2、使用WebService更新AutoCompleteBox的ItemSource。
这里需要使用Populating事件,如果使用TextChanged等事件异步更新AutoCompleteBox将会失败。
关于Populating:
MSDN:http://msdn.microsoft.com/en-us/library/system.windows.controls.autocompletebox(v=vs.95).aspx
Populating的解释:Occurs when the AutoCompleteBox is populating the drop-down with possible matches based on theText property.
这里展示部分主要的代码,完整代码可以clone 我的git repository查看:
MainPage.xaml
public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); wordAutoCompleteBox.ItemFilter = (search, item) => { Person person = item as Person; if (person != null) { return person.FirstName.Contains(search); } return false; }; } private void WordAutoCompleteBox_OnPopulating(object sender, PopulatingEventArgs e) { var client = new PersonServiceSoapClient(); client.GetPersonsCompleted += GetPersonsCompleted; client.GetPersonsAsync(); } private void GetPersonsCompleted(object sender, GetPersonsCompletedEventArgs e) { wordAutoCompleteBox.ItemsSource = e.Result; wordAutoCompleteBox.PopulateComplete(); } }
服务器端代码:
namespace autocomplete_custom_searchmode_demo.Web { /// <summary> /// Summary description for PersonService /// </summary> [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [System.ComponentModel.ToolboxItem(false)] // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. // [System.Web.Script.Services.ScriptService] public class PersonService : System.Web.Services.WebService { [WebMethod] public List<Person> GetPersons() { return Persons(); } private List<Person> Persons() { var persons = new List<Person>(); persons.Add(new Person { FirstName = "java", SecondName = "china" }); persons.Add(new Person { FirstName = "csharp", SecondName = "japan" }); persons.Add(new Person { FirstName = "cplusplus", SecondName = "india" }); persons.Add(new Person { FirstName = "ruby", SecondName = "china" }); persons.Add(new Person { FirstName = "python", SecondName = "korea" }); return persons; } } [DataContract] public class Person { [DataMember] public String FirstName { get; set; } [DataMember] public String SecondName { get; set; } public override String ToString() { return FirstName + " " + SecondName; } } }
OK, done.