在最近一个月的工作中,一直在开发一个简单的文本框,它具有自定义的自动完成过滤功能。这个想法是受到GMail搜索功能的启发。这个自定义控件需要具备以下所有功能,以满足项目需求:
它必须非常容易使用,并且尽可能少地与项目代码集成。 它需要与WCF兼容。想法是,像GMail一样,创建一个分层应用程序,因此过滤功能需要在服务器端执行,然后通过WCF通道传输结果。 它需要过滤自定义数据(可以来自数据库或自定义列表),并在多个字段上进行搜索,就像GMail一样,并建议相似的结果。 所有过滤都需要以异步方式完成,因此将使用响应式库。 它需要与键盘和鼠标交互。 它需要强制用户从可用列表中选择一个项目。 它必须完全兼容项目中使用的MVVM模板。 它需要通知用户正在应用过滤,以及过滤完成时。 它需要让用户能够浏览结果列表并选择一个项目。 除了过滤代码之外,所有代码都需要封装在自定义控件内。 支持水印文本。 还需要能够在视图模型中选择一个默认选项,并在控件上反映出来。
在互联网上找到了几个示例源代码,但都没有满足上述所有点。没有编写整个代码。这个项目是基于这篇文章的优秀内容: 。 欢迎任何关于如何改进这段代码的建议。
几个月来,一直在将一个VB6应用程序迁移到新技术上。经过几周的网络冲浪和搜索,学习新技术,设法开始了项目。面临的一个问题是如何让用户从几个表中选择一个项目。例如,需要让用户为顾客订单选择一个顾客表中的顾客。这需要通过WCF通道完成。通常,会在客户端填充一个组合框,让用户选择一个,但这是低效的。这个想法是让用户输入一些数据(至少三个字符),以帮助过滤数据,并将可能的匹配项返回给最终用户。
使用代码
从XAML的角度来看,使用这个控件非常简单:
<Window x:Class="TextBoxAutoCompleteTest.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ac="clr-namespace:WpfAutoComplete.Controls;assembly=WpfAutoComplete" Title="Autocomplete Text Box Project" Height="300" Width="300">
<Grid>
<StackPanel>
<Label Content="This is an Autocomplete Textbox" />
<ac:TextBoxAutoComplete Name="autoTxtBoxEng" SearchDataProvider="{Binding Path=MySearchProviderEng}" SelectedListBoxValue="{Binding Path=PhraseNumber, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" WatermarkText="Type in filtering text here..." />
</StackPanel>
</Grid>
</Window>
关于代码的一些说明: SearchDataProvider属性是将用于数据过滤的类。该类需要实现ISearchDataProvider接口。 SelectedListBoxValue是可选的,指向VM上的属性,由控件更新。 WatermarkText是当没有输入时显示的文本。
这是一个简单的SearchDataProvider类的示例,使用字典作为示例:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TextBoxAutoCompleteTest
{
class MyDataProviderEng : WpfAutoComplete.ISearchDataProvider
{
public WpfAutoComplete.SearchResult DoSearch(string searchTerm)
{
return new WpfAutoComplete.SearchResult
{
SearchTerm = searchTerm,
Results = dict.Where(item => item.Value.ToUpperInvariant().Contains(searchTerm.ToUpperInvariant())).ToDictionary(v => v.Key, v => v.Value)
};
}
public WpfAutoComplete.SearchResult SearchByKey(object Key)
{
return new WpfAutoComplete.SearchResult
{
SearchTerm = null,
Results = dict.Where(item => item.Key.ToString() == Key.ToString()).ToDictionary(v => v.Key, v => v.Value)
};
}
private readonly Dictionary
很容易将此代码适应于使用WCF服务进行过滤并返回可用选项,而不是预定义的字典。看看这个新的ISearchDataProvider实现:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Ohmio.Client.DataProviders
{
class DataProviderClientes : WpfAutoComplete.ISearchDataProvider
{
private OhmioService.OhmioServiceClient serviceClient = new OhmioService.OhmioServiceClient();
public WpfAutoComplete.SearchResult DoSearch(string searchTerm)
{
return new WpfAutoComplete.SearchResult
{
SearchTerm = searchTerm,
Results = (serviceClient.EnumClientes(searchTerm.ToUpperInvariant())).ToDictionary(x => (object)x.Key, y => y.Descripcion)
};
}
public WpfAutoComplete.SearchResult SearchByKey(object Key)
{
return new WpfAutoComplete.SearchResult
{
SearchTerm = null,
Results = (serviceClient.EnumClientes(Key.ToString())).ToDictionary(v => (object)v.Key, v => v.Descripcion)
};
}
}
}
在这种情况下,使用了一个WCF服务,该服务有一个名为EnumClientes的方法。这个方法接受一个过滤参数,在数据库上执行过滤,然后返回一个List