TextBox值更改时更新ComboBox项

时间:2013-11-17 15:15:21

标签: c# wpf xaml mvvm combobox

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

我目前有一个TextBox&窗口窗体上的ComboBox。

目前,我想安排这样当用户在TextBox中输入Access DB文件路径时,ComboBox将自动更新,使其可用的Items是MDB文件中的Tables Name。当用户将MDB文件路径更改为另一个时,ComboBox项也将刷新。

我已经在GUI的ViewModel中准备了以下属性。

...
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}"/>
...

所有我不知道的是如何将Model Method链接到ViewModel,并使ComboBox知道MdbDir已更改。

有什么想法添加编码,同时最小化对当前编码的修改?

非常感谢提前:)

2 个答案:

答案 0 :(得分:0)

你可以用两种方式做到这一点。

当您在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而不是list

答案 1 :(得分:0)

您的ViewModel可以保留对Model的引用,因为ViewModel可以被视为您wrapper的{​​{1}}。

您可以拨打Model方法Model,例如:

ReturnMdbTblList

这是直接实施和有效的。我的个人偏好不会放在public string MdbDir { get { return this.mdbDir; } set { this.mdbDir = value; RaisePropertyChanged("MdbDir"); this.MdbTblList = this.model.ReturnMdbTblList(value); } } get set方法中的任何内容中,这些方法不会直接影响它正在访问的properties或通知其已更改的其他人。这只是我的偏好,其他人可能会乐意这样做,我并不是说这是错误的。

我会使用按钮上的field拨打您的DelegateCommand

模型,ViewMode&amp; DelegateCommand

ReturnMdbTdlList

<强> XAML

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);
        }
    }
}

我们将<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> 的{​​{1}}属性绑定到Command中的Button,我们还绑定了UpdateMdbTblCommand的{​​{1}}属性} MyViewModel的{​​{1}}属性。按下CommandParameter后,会执行Button,然后调用MdbDir传递MyViewModel的值作为参数,然后更新Button属性UpdateMdbTblCommand

正如我所说UpdateMdbTbl将是我的首选方法,然而,考虑到你必须编写什么来实现前一个例子中可以做的事情,这可能是过度的。