【问题标题】:UWP Binding to AutoSuggestBox in MVVMUWP 绑定到 MVVM 中的 AutoSuggestBox
【发布时间】:2016-04-09 18:59:47
【问题描述】:

我正在 UWP 中调用 AutoSuggestBox 控件的 QuerySubmitted 命令。 该命令绑定到视图模型中的 ICommand。 问题是它需要接受纯 UI 的 AutoSuggestBoxQuerySubmittedEventArgs,它在 MVVM 中是不可接受的。

我的代码是这样的:

<AutoSuggestBox Name="SearchAutoSuggestBox"
                PlaceholderText="Search by keywords"
                QueryIcon="Find"
                >
    <interactivity:Interaction.Behaviors>
        <core:EventTriggerBehavior EventName="QuerySubmitted">
            <core:InvokeCommandAction Command="{x:Bind ViewModel.SearchCommand}" />
        </core:EventTriggerBehavior>
    </interactivity:Interaction.Behaviors>
</AutoSuggestBox>

我的视图模型看起来像这样:

public DelegateCommand<AutoSuggestBoxQuerySubmittedEventArgs> SearchCommand { get; }

public MainPageViewModel()
{
    SearchCommand = new DelegateCommand<AutoSuggestBoxQuerySubmittedEventArgs>(ExecuteMethod);
}

private void ExecuteMethod(AutoSuggestBoxQuerySubmittedEventArgs o)
{
    // CODE HERE
}

ofcours AutoSuggestBoxQuerySubmittedEventArgs 在视图模型中是不可接受的。 寻找替代品... 同样适用于 SuggestionChosen...

【问题讨论】:

  • EventTriggerBehavior 的 MSDN 页面表示仅支持事件的子集,而 QuerySubmitted 不是其中之一。您是否为此实施了新行为?

标签: mvvm binding uwp autosuggest


【解决方案1】:

InvokeCommandAction 有一个名为 InputConverter 的参数,您可以使用该参数将事件 args 转换为可以传递给 ViewModel 的其他参数。

首先创建一个 IValueConverter 类以从事件参数中提取您需要的内容,如下所示:-

public class AutoSuggestQueryParameterConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
       {
          // cast value to whatever EventArgs class you are expecting here
          var args = (AutoSuggestBoxQuerySubmittedEventArgs)value;
          // return what you need from the args
          return (string)args.ChosenSuggestion;
       }
}

然后像这样在您的 XAML 中使用该转换器:

<Page.Resources>
     <converters:AutoSuggestQueryParameterConverter x:Key="ArgsConverter" />
</Page.Resources>

<AutoSuggestBox Name="SearchAutoSuggestBox"
            PlaceholderText="Search by keywords"
            QueryIcon="Find">
    <interactivity:Interaction.Behaviors>
      <core:EventTriggerBehavior EventName="QuerySubmitted">
        <core:InvokeCommandAction 
              Command="{x:Bind ViewModel.SearchCommand}"
              InputConverter="{StaticResource ArgsConverter}" />
      </core:EventTriggerBehavior>
    </interactivity:Interaction.Behaviors>
</AutoSuggestBox>

最后在您的视图模型中更改您的命令以接受字符串作为参数。所以你的虚拟机里会有以下内容:

public DelegateCommand<string> SearchCommand { get; }

public MainPageViewModel()
{
    SearchCommand = new DelegateCommand<string>(ExecuteMethod);
}

private void ExecuteMethod(string o)
{
    // CODE HERE
}

【讨论】:

    【解决方案2】:

    您可以将搜索字符串(文本属性)绑定到视图模型属性,并将事件绑定到无参数方法。这样视图模型就不必处理 UI 对象了:

    XAML:

    <AutoSuggestBox Header="What's your name?"
                    TextChanged="{x:Bind ViewModel.FilterUsuals}"
                    QuerySubmitted="{x:Bind ViewModel.ProcessQuery}"
                    SuggestionChosen="{x:Bind ViewModel.ProcessChoice}"
                    ItemsSource="{x:Bind ViewModel.Usuals, Mode=OneWay}"
                    Text="{x:Bind ViewModel.SearchText, Mode=TwoWay}"
                    QueryIcon="Find" />
    

    后面的代码:

    public class MainPageViewModel : SomeViewModelBaseClass
    {
        /* Boilerplate code and constructor not included */
    
        private string _SearchText;
        public string SearchText {/* getter and setter INotyfyPropertyChange compliant */ }
    
        private List<string> _Usuals; // Initialized on constructor
        public string Usuals {/* getter and setter INotyfyPropertyChange compliant */ }
    
    
        public void FilterUsuals()
        {
            // the search string is in SearchText Example:
            Usuals = _UsualsStore.Where(u => u.Contains(_SearchText.ToLower())).ToList();
        }
    
        public void ProcessQuery() { /* TODO - search string is in SearchText */ }
    
        public void ProcessChoice() { /* TODO - search string is in SearchText */ }
    }
    

    【讨论】:

      【解决方案3】:

      如果你不介意使用non pure MVVM 方式。

      MainPage.xaml

      <AutoSuggestBox Name="SearchAutoSuggestBox"
              PlaceholderText="Search by keywords"
              QueryIcon="Find" QuerySubmitted="{x:Bind ViewModel.SearchQuerySubmitted}" IsEnabled="{x:Bind ViewModel.CanExecuteSearchCommand, Mode=TwoWay}"
              >
      </AutoSuggestBox>
      

      MainPageViewModel.cs

      public class MainPageViewModel : INotifyPropertyChanged
      {
          private bool _canExecuteSearchCommand;
      
          public MainPageViewModel()
          {
              this.CanExecuteSearchCommand = true;
          }
      
          public bool CanExecuteSearchCommand
          {
              get { return _canExecuteSearchCommand; }
              set
              {
                  bool changed = _canExecuteSearchCommand != value;
                  _canExecuteSearchCommand = value;
      
                  if(changed)
                      this.OnPropertyChanged();
              }
          }
      
          public void SearchQuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
          {
              // Just example disabling SearchBox
              this.CanExecuteSearchCommand = false;
          }
      
          public event PropertyChangedEventHandler PropertyChanged;
      
          protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
          {
              PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
          }
      }
      

      MainPage.cs

      MainPageViewModel ViewModel = new MainPageViewModel();
      

      【讨论】:

        【解决方案4】:

        UWP 绑定 Command/DelegateAutoSuggestBox in MVVM

        对于 UWP 移动应用程序

        创建一个 DelegateCommand 类

        public class DelegateCommand<T> : ICommand
        {
            private readonly Action<T> executeAction;
            Func<object, bool> canExecute;
        
            public event EventHandler CanExecuteChanged;
        
            public DelegateCommand(Action<T> executeAction)
                : this(executeAction, null)
            {
                //var a = ((Page)(((Func<object, bool>)(executeAction.Target)).Target)).Name;
                //((ViewModel.VMBranchSelection)(executeAction.Target)).;
        
            }
        
            public DelegateCommand(Action<T> executeAction, Func<object, bool> canExecute)
            {
                this.executeAction = executeAction;
                this.canExecute = canExecute;
            }
        
            public bool CanExecute(object parameter)
            {
                return canExecute == null ? true : canExecute(parameter);
            }
        
            public void Execute(object parameter)
            {
                executeAction((T)parameter);
            }
            public void RaiseCanExecuteChanged()
            {
                EventHandler handler = this.CanExecuteChanged;
                if (handler != null)
                {
                    handler(this, new EventArgs());
                }
            }
        }
        

        在视图模型中

            public ICommand SuggessionSelectCity_QuerySubmitted
            {
                get { return new DelegateCommand<AutoSuggestBoxQuerySubmittedEventArgs>(this.SuggessionSelectCityQuerySubmitted); }
            }
        
            private void     SuggessionSelectCityQuerySubmitted(AutoSuggestBoxQuerySubmittedEventArgs obj)
            {
                if (obj.ChosenSuggestion != null)
                {
                    AutosuggestionTextBoxName.Text = ((ModelName)   (obj.ChosenSuggestion)).Model's Property name;
        //or
        AutosuggestionTextBoxName.Text =(obj.ChosenSuggestion).property name    
                }
                else
                {
        
                }
            }
        

        在 XAML 代码中

        <AutoSuggestBox Grid.Column="1" x:Name="SuggessionSelectCity"  
                    PlaceholderText="Search by keywords" QueryIcon="Find"
                    ItemsSource="{Binding PApplicantCityList}"
        
                    HorizontalAlignment="Center" VerticalAlignment="Center" DisplayMemberPath="Description" Width="250" Height="45">
        
                        <Interactivity:Interaction.Behaviors>
                            <Core:EventTriggerBehavior EventName="TextChanged">
                                <Core:EventTriggerBehavior.Actions>
                                    <Core:InvokeCommandAction Command="{Binding SuggessionSelectCityTextChange}"/>
                                </Core:EventTriggerBehavior.Actions>
                            </Core:EventTriggerBehavior>
        
                            <Core:EventTriggerBehavior EventName="QuerySubmitted">
                                <Core:EventTriggerBehavior.Actions>
                                    <Core:InvokeCommandAction Command="{Binding SuggessionSelectCity_QuerySubmitted}"/>
                                </Core:EventTriggerBehavior.Actions>
                            </Core:EventTriggerBehavior>
        
                            <Core:EventTriggerBehavior EventName="SuggestionChosen">
                                <Core:EventTriggerBehavior.Actions>
                                    <Core:InvokeCommandAction Command="{Binding SuggessionSelectCitySuggestionChosen}"/>
                                </Core:EventTriggerBehavior.Actions>
                            </Core:EventTriggerBehavior>
        
        
                        </Interactivity:Interaction.Behaviors>
                    </AutoSuggestBox>
                </Grid>
        

        在视图模型中为 Autosuggestion TextBox Itemssource 创建一个列表

        private ObservableCollection<ResultMasterModel> ApplicantCityList;
            public ObservableCollection<ResultMasterModel> PApplicantCityList
            {
                get { return ApplicantCityList; }
                set { this.SetProperty(ref this.ApplicantCityList, value); }
            }
        

        在上面的列表中添加一些硬编码值

        在模型文件夹中创建模型

        public class ResultMasterModel
        {   
            public string Code { get; set; }
            public string Description { get; set; }
        }
        

        【讨论】:

          猜你喜欢
          • 2017-04-08
          • 2017-05-14
          • 1970-01-01
          • 2018-01-20
          • 1970-01-01
          • 2017-10-30
          • 1970-01-01
          • 2020-08-02
          • 2017-07-27
          相关资源
          最近更新 更多