【问题标题】:Update ComboBox Items when TextBox value changed当 TextBox 值更改时更新 ComboBox 项
【发布时间】:2013-11-30 16:34:46
【问题描述】:

您好,我是使用 C# 尝试生成 WPF(MVVM) 的初学者。

我目前在窗口窗体上有一个文本框和一个组合框。

目前,我想安排这样当用户在 TextBox 中输入 Access DB 文件路径时,ComboBox 将自动更新,以便其可用项目是 MDB 文件中的表名称。当用户将 MDB 文件路径更改为另一个时,组合框项目也将被刷新。

我已经在 GUI 的 ViewModel 中的 Properties 下面准备好了。

...
public string MdbDir { get{;} set {; RaisePropertyChanged("MdbDir");} }
public List<string> MdbTblList { get{;} set{...; RaisePropertyChanged("MdbTblList");}} 
...

我已经在模型中准备了下面的方法。

...
public List<string> ReturnMdbTblList(string mdbDir)
{
    List<string> mdbTblList = new List<string>();
    oCat = new ADOX.Catalog();
    oCat.ActiveConnection = oConn;
    foreach (ADOX.Table oTable in oCat.Tables)
    {
        mdbTblList.Add(oTable.Name);
    }
    return mdbTblList;
}
...

我已经在View.xaml下面准备好了

...
<TextBox Grid.Column="1" Grid.ColumnSpan="2" Text="{Binding MdbDir}" />
<ComboBox Grid.Column="1" Grid.Row="3" SelectedItem="{Binding Path=SelectedMdbTbl,Mode=TwoWay}" ItemsSource="{Binding MdbTblList}"/>
...

我不知道的是如何将模型方法链接到 ViewModel,并让 ComboBox 知道 MdbDir 发生了变化。

您知道还要添加什么编码,同时尽量减少对当前编码的修改吗?

提前非常感谢:)

【问题讨论】:

    标签: c# wpf xaml mvvm combobox


    【解决方案1】:

    您可以通过两种方式做到这一点。

    当您在 textBox 中键入路径并按 Tab 时,将调用属性 MdbDir 的 Set 部分。所以你可以像下面这样调用方法。在该方法方法中,您可以从模型中获取详细信息并将其更新到 UI。

     public string MdbDir 
     { 
         get
         {
            ;
         } set 
         {
              ; 
              RaisePropertyChanged("MdbDir");
              UpDateTheList()
         } 
      }
    

    或者您可以在 UI 上设置按钮,然后单击该按钮可以执行相同的操作。要将命令绑定到按钮,您可以参考以下链接

    http://theprofessionalspoint.blogspot.in/2013/04/icommand-interface-and-relaycommand.html

    http://www.codeproject.com/Articles/126249/MVVM-Pattern-in-WPF-A-Simple-Tutorial-for-Absolute

    再观察一下,如果您每次都创建新列表,那么 List 就可以了,但是如果您使用现有列表添加或删除某些内容,那么它对您不起作用,您必须使用 observablecollection 而不是列表

    【讨论】:

      【解决方案2】:

      您的ViewModel 可以保留对您的Model 的引用,因为ViewModel 可以被视为您的Modelwrapper

      您可以调用您的Model 方法ReturnMdbTblList,例如:

      public string MdbDir
      {
          get
          {
              return this.mdbDir;
          }
          set
          {
              this.mdbDir = value;
              RaisePropertyChanged("MdbDir");
              this.MdbTblList = this.model.ReturnMdbTblList(value);
          }
      }
      

      这是直接实施和有效的。我个人的偏好是不要在propertiespropertiesgetset 方法中放入任何不直接影响它正在访问或通知其他人它已更改的field 的内容。不过,这只是我的偏好,其他人可能会很乐意这样做,我并不是说这是错误的。

      我会在按钮上使用DelegateCommand 来拨打您的ReturnMdbTdlList

      模型、视图模式和委托命令

      public class MyViewModel : INotifyPropertyChanged
      {
          private readonly MyModel model;
      
          private string mdbDir;
          public string MdbDir
          {
              get
              {
                  return this.mdbDir;
              }
              set
              {
                  this.mdbDir = value;
                  RaisePropertyChanged("MdbDir");
              }
          }
      
          private List<string> mdbTblList;
          public List<string> MdbTblList
          {
              get
              {
                  return this.mdbTblList;
              }
              set
              {
                  this.mdbTblList = value;
                  RaisePropertyChanged("MdbTblList");
              }
          }
      
          private DelegateCommand updateMdbTblListCommand;
          public ICommand UpdateMdbTblListCommand
          {
              get
              {
                  return this.updateMdbTblListCommand ??
                          (this.updateMdbTblListCommand = new DelegateCommand(this.UpdateMdbTblList));
              }
          }
      
          public MyViewModel()
          {
              // This would idealy be injected via the constructor
              this.model = new MyModel();
          }
      
          private void UpdateMdbTblList(object obj)
          {
              var param = obj as string;
              this.MdbTblList = this.model.ReturnMdbTblList(param);
          }
      
          #region [ INotifyPropertyChanged ]
      
          public event PropertyChangedEventHandler PropertyChanged;
      
          [NotifyPropertyChangedInvocator]
          protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
          {
              var handler = PropertyChanged;
              if (handler != null)
              {
                  handler(this, new PropertyChangedEventArgs(propertyName));
              }
          }
      
          #endregion
      }
      
      public class MyModel
      {
          public List<string> ReturnMdbTblList(string mdbDir)
          {
              // Do soemthing
              return new List<string>();
          }
      }
      
      public class DelegateCommand : ICommand
      {
          private readonly Predicate<object> _canExecute;
          private readonly Action<object> _execute;
      
          public event EventHandler CanExecuteChanged;
      
          public DelegateCommand(Action<object> execute)
              : this(execute, null)
          {
          }
      
          public DelegateCommand(Action<object> execute,
                          Predicate<object> canExecute)
          {
              _execute = execute;
              _canExecute = canExecute;
          }
      
          public bool CanExecute(object parameter)
          {
              return this._canExecute == null || this._canExecute(parameter);
          }
      
          public void Execute(object parameter)
          {
              _execute(parameter);
          }
      
          public void RaiseCanExecuteChanged()
          {
              if (CanExecuteChanged != null)
              {
                  CanExecuteChanged(this, EventArgs.Empty);
              }
          }
      }
      

      XAML

      <StackPanel Orientation="Horizontal" VerticalAlignment="Top">
          <TextBox Height="23" Margin="10" Width="200" Text="{Binding MdbDir}" />
          <Button Content="Click Me"  Width="100" Height="25" Margin="10" Command="{Binding Path=UpdateMdbTblListCommand}" CommandParameter="{Binding Path=MdbDir}" />
      </StackPanel>
      

      我们将ButtonCommand 属性绑定到MyViewModel 中的UpdateMdbTblCommand,我们还将ButtonCommandParameter 属性绑定到MyViewModelMdbDir 属性。当按下Button 时,会执行UpdateMdbTblCommand,然后调用UpdateMdbTbl,将MdbDir 的值作为参数传递并随后更新MyViewModelMdbTblList 属性。

      正如我所说,DelegateCommand 将是我的首选方法,但是,考虑到您必须编写的内容以实现前一个示例中可以完成的操作时,这可能是矫枉过正。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-12
        • 2019-11-07
        • 2016-10-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多