您好我是初学者使用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已更改。
有什么想法添加编码,同时最小化对当前编码的修改?
非常感谢提前:)
答案 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
将是我的首选方法,然而,考虑到你必须编写什么来实现前一个例子中可以做的事情,这可能是过度的。