简体   繁体   English

当TextBox值更改时更新ComboBox项目

[英]Update ComboBox Items when TextBox value changed

Hi I am beginner using C# trying to produce a WPF(MVVM). 嗨,我是初学者,正在使用C#尝试生成WPF(MVVM)。

I have currently a TextBox & a ComboBox on a Window Form. 我目前在窗口窗体上有一个TextBox和ComboBox。

At the moment, I would like to arrange such that when user input an Access DB file path into the TextBox, the ComboBox will be automatically updated such that its available Items is the Tables Name in the MDB file. 此刻,我想进行安排,以便当用户在TextBox中输入Access DB文件路径时,ComboBox将自动更新,以使其可用的项成为MDB文件中的表名。 When user changed the MDB file path to another, ComboBox Items will be refreshed as well. 当用户将MDB文件路径更改为另一个路径时,ComboBox项目也会被刷新。

I have already prepared below Properties in the GUI's ViewModel. 我已经在GUI的ViewModel中的“属性”下面进行了准备。

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

I have already prepared below method in the Model. 我已经在模型中准备了以下方法。

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

I have already prepared below in View.xaml 我已经在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}"/>
...

All I don't know is how to link the Model Method to ViewModel, and to make the ComboBox aware of MdbDir changed. 我所不知道的是如何将模型方法链接到ViewModel,以及如何使ComboBox知道MdbDir已更改。

Any idea on what else to add the coding and at the same time minimize the amendment on the current piece of coding? 有什么想法可以添加编码,同时又可以最大程度地减少对当前编码的修改?

Thanks very much in advance :) 首先十分感谢 :)

You can do that in two ways. 您可以通过两种方式做到这一点。

When ever you type the path in textBox and press tab, the Set part of the property MdbDir will be called. 每当您在textBox中键入路径并按tab时,都会调用属性MdbDir的Set部分。 So you can call method like below. 因此,您可以调用以下方法。 And in that method method you can fetch the details from the Model and update it to the UI. 在这种方法中,您可以从模型中获取详细信息并将其更新到UI。

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

Or you can have button on the UI and click of that can do the same thing. 或者,您可以在UI上单击按钮,然后单击该按钮可以执行相同的操作。 to Bind commands to buttons you can refer the below links 将命令绑定到按钮,您可以参考以下链接

http://theprofessionalspoint.blogspot.in/2013/04/icommand-interface-and-relaycommand.html 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 http://www.codeproject.com/Articles/126249/MVVM-Pattern-in-WPF-A-Simple-Tutorial-for-Absolute

One more observation, if your new creating list every time then List is fine, but if your adding or removing something with already existing list then it'll not work for you, you have to use observablecollection instead of list 再观察一下,如果每次都使用新创建的列表,则“列表”就可以了,但是如果您添加或删除已经存在的列表,则对您不起作用,您必须使用observablecollection而不是列表

It is acceptable for your ViewModel to maintain a reference to your Model as the ViewModel can be thought of as a wrapper for your Model . ViewModel可以保留对Model的引用,因为ViewModel可以视为Modelwrapper

You could put a call to your Model method ReturnMdbTblList such as: 您可以调用Model方法ReturnMdbTblList例如:

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

This is straight forward to implement and effective. 这是直接实施和有效的。 My personal preference is not put anything inside the get and set methods of properties that do not directly affect the field it is accessing or notifying others it has changed. 我个人的喜好是不会在propertiesgetset方法中放置任何内容,这些properties不会直接影响它正在访问的field或通知其他人已更改的properties That is just my preference though, others may be happy to do so and I am not saying it is wrong. 不过,这只是我的偏爱,其他人可能很乐意这样做,我并不是说这是错误的。

I would use a DelegateCommand on the button to make the call to your ReturnMdbTdlList : 我会在按钮上使用DelegateCommand来调用您的ReturnMdbTdlList

Model, ViewMode & DelegateCommand 模型,ViewMode和DelegateCommand

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 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>

We bind the Command property of the Button to our UpdateMdbTblCommand in the MyViewModel , we also bind the CommandParameter property of the Button to the MdbDir property of MyViewModel . 我们的绑定Command中的属性Button我们UpdateMdbTblCommandMyViewModel ,我们也将结合CommandParameter的财产ButtonMdbDir财产MyViewModel When the Button is pressed the UpdateMdbTblCommand is executed which in turn calls the UpdateMdbTbl passing along the value of MdbDir as an argument and subsequently updating the MdbTblList property of MyViewModel . Button被按下时UpdateMdbTblCommand执行这又调用UpdateMdbTbl沿的值传递MdbDir作为参数,并随后更新所述MdbTblList的属性MyViewModel

As I said the DelegateCommand would be my preferred method, however, it may be overkill when taking into consideration what you have to write to achieve what can be done in the former example. 正如我说过的那样, DelegateCommand是我的首选方法,但是考虑到为实现前一个示例中可以完成的操作而必须写的内容时,这可能会显得过高。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM