如何将AutoCompleteBox.PopulateComplete方法与MVVM范例结合起来?
以下是设置: 我有一个由viewmodel填充的自动完成框,它从WCF服务获取数据。因此,到目前为止,它非常简单明了 现在,我试图遵循MVVM的原则,通过MVVM,viewmodel对视图本身一无所知。这很好,因为我将自动完成框的填充事件绑定到了viewmodel的一个方法 因此,视图模型正在抓取数据,而视图正在等待。还没有问题 现在,视图模型获得了数据,我将结果集合传递给绑定到控件ItemSource属性的属性。屏幕上什么也没发生 我去MSDN,寻找官方批准的处理这种情况的方法():如何将AutoCompleteBox.PopulateComplete方法与MVVM范例结合起来?,mvvm,silverlight-4.0,silverlight-toolkit,Mvvm,Silverlight 4.0,Silverlight Toolkit,以下是设置: 我有一个由viewmodel填充的自动完成框,它从WCF服务获取数据。因此,到目前为止,它非常简单明了 现在,我试图遵循MVVM的原则,通过MVVM,viewmodel对视图本身一无所知。这很好,因为我将自动完成框的填充事件绑定到了viewmodel的一个方法 因此,视图模型正在抓取数据,而视图正在等待。还没有问题 现在,视图模型获得了数据,我将结果集合传递给绑定到控件ItemSource属性的属性。屏幕上什么也没发生 我去MSDN,寻找官方批准的处理这种情况的方法(): 将Mi
- 将MinimumPrefixLength和MinimumPopulateDelay属性设置为 值大于默认值以最小化对Web服务的调用
- 处理填充事件并设置填充事件参数。取消 属性设置为true
- 执行必要的处理并将ItemsSource属性设置为 所需的项目集合
- 调用PopulateComplete方法以通知自动完成框显示 下拉列表
那么,我到底该如何在不违反MVVM原则的情况下从视图模型中调用PopulateComplete视图方法呢?如果您使用Blend的交互库,其中一个选项是为
自动完成框添加的:
public class AsyncAutoCompleteBehavior : Behavior<AutoCompleteBox>
{
public static readonly DependencyProperty SearchCommandProperty
= DependencyProperty.Register("SearchCommand", typeof(ICommand),
typeof(AsyncAutoCompleteBehavior), new PropertyMetadata(null));
public ICommand SearchCommand
{
get { return (ICommand)this.GetValue(SearchCommandProperty); }
set { this.SetValue(SearchCommandProperty, value); }
}
protected override void OnAttached()
{
this.AssociatedObject.Populating += this.PopulatingHook;
}
protected override void OnDetaching()
{
this.AssociatedObject.Populating -= this.PopulatingHook;
}
private void PopulatingHook(object sender, PopulatingEventArgs e)
{
var command = this.SearchCommand;
var parameter = new SearchCommandParameter(
() => this.AssociatedObject
.Dispatcher
.BeginInvoke(this.AssociatedObject.PopulateComplete),
e.Parameter);
if (command != null && command.CanExecute(parameter))
{
// Cancel the pop-up, execute our command which calls
// parameter.Complete when it finishes
e.Cancel = true;
this.SearchCommand.Execute(parameter);
}
}
}
此时,您需要做两件事:
把这种行为联系起来
<sdk:AutoCompleteBox MinimumPopulateDelay="250" MinimumPrefixLength="2" FilterMode="None">
<i:Interaction.Behaviors>
<b:AsyncAutoCompleteBehavior SearchCommand="{Binding Search}" />
</i:Interaction.Behaviors>
</sdk:AutoCompleteBox>
创建一个DelegateCommand,用于处理aysnc搜索
public class MyViewModel : ViewModelBase
{
public ICommand Search
{
get;
private set;
}
private void InitializeCommands()
{
this.Search = new DelegateCommand<SearchCommandParamater>(DoSearch);
}
private void DoSearch(SearchCommandParameter parameter)
{
var client = new WebClient();
var uri = new Uri(
@"http://www.example.com/?q="
+ HttpUtility.UrlEncode(parameter.SearchText));
client.DownloadStringCompleted += Downloaded;
client.DownloadStringAsync(uri, parameter);
}
private void Downloaded(object sender, DownloadStringCompletedEventArgs e)
{
// Do Something with 'e.Result'
((SearchCommandParameter)e.UserState).Complete();
}
}
公共类MyViewModel:ViewModelBase
{
公共ICommand搜索
{
得到;
私人设置;
}
私有void initializeCommand()
{
this.Search=newdelegateCommand(DoSearch);
}
私有void DoSearch(SearchCommandParameter参数)
{
var client=new WebClient();
var uri=新uri(
@"http://www.example.com/?q="
+HttpUtility.UrlEncode(parameter.SearchText));
client.DownloadStringCompleted+=已下载;
client.DownloadStringAsync(uri,参数);
}
已下载私有void(对象发送方,下载StringCompletedEventArgs e)
{
//用“e.Result”做点什么
((SearchCommandParameter)e.UserState).Complete();
}
}
您介意我问一下,您从哪里获得silverlight的System.Threading.Tasks?您认为SearchCommand与异步交互有什么关系?我的意思是,在Execute的主体中有一个对WCF服务的调用,但Execute没有任何要返回的内容,因此我无法将asnynchrouns调用的句柄从命令的Execute方法传递给WCF。总之,在调用命令的Execute方法之后,似乎会立即调用PopulateComplete方法,而无需等待来自命令的结果WCF@bonomo:您可以控制Execute命令何时返回,但如果不想返回,也可以。我将继续更改此项,以消除对第三方物流的任何依赖。很抱歉,我没有检查您所做的更新。它使用一个特殊的请求对象。非常感谢。让它发挥作用。FilterMode需要设置为“无”,请更新您的XAML。事实上我能行,没关系。
public class MyViewModel : ViewModelBase
{
public ICommand Search
{
get;
private set;
}
private void InitializeCommands()
{
this.Search = new DelegateCommand<SearchCommandParamater>(DoSearch);
}
private void DoSearch(SearchCommandParameter parameter)
{
var client = new WebClient();
var uri = new Uri(
@"http://www.example.com/?q="
+ HttpUtility.UrlEncode(parameter.SearchText));
client.DownloadStringCompleted += Downloaded;
client.DownloadStringAsync(uri, parameter);
}
private void Downloaded(object sender, DownloadStringCompletedEventArgs e)
{
// Do Something with 'e.Result'
((SearchCommandParameter)e.UserState).Complete();
}
}