[英]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
可以视为Model
的wrapper
。
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. 我个人的喜好是不会在
properties
的get
和set
方法中放置任何内容,这些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
我们UpdateMdbTblCommand
在MyViewModel
,我们也将结合CommandParameter
的财产Button
到MdbDir
财产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.