如何将AutoCompleteBox.PopulateComplete方法与MVVM范例结合起来?

如何将AutoCompleteBox.PopulateComplete方法与MVVM范例结合起来?,mvvm,silverlight-4.0,silverlight-toolkit,Mvvm,Silverlight 4.0,Silverlight Toolkit,以下是设置: 我有一个由viewmodel填充的自动完成框,它从WCF服务获取数据。因此,到目前为止,它非常简单明了 现在,我试图遵循MVVM的原则,通过MVVM,viewmodel对视图本身一无所知。这很好,因为我将自动完成框的填充事件绑定到了viewmodel的一个方法 因此,视图模型正在抓取数据,而视图正在等待。还没有问题 现在,视图模型获得了数据,我将结果集合传递给绑定到控件ItemSource属性的属性。屏幕上什么也没发生 我去MSDN,寻找官方批准的处理这种情况的方法(): 将Mi

以下是设置: 我有一个由viewmodel填充的自动完成框,它从WCF服务获取数据。因此,到目前为止,它非常简单明了

现在,我试图遵循MVVM的原则,通过MVVM,viewmodel对视图本身一无所知。这很好,因为我将自动完成框的填充事件绑定到了viewmodel的一个方法

因此,视图模型正在抓取数据,而视图正在等待。还没有问题

现在,视图模型获得了数据,我将结果集合传递给绑定到控件ItemSource属性的属性。屏幕上什么也没发生

我去MSDN,寻找官方批准的处理这种情况的方法():

  • 将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();
        }
    }