我有一个 WPF 应用程序,它有多个组合框和按钮。我正在使用此应用程序学习 MVVM 模型。第一个组合框将显示数据库实例列表。这是在应用程序开始时完成的。这工作正常。
数据库实例组合框旁边有一个按钮对象。当用户单击此按钮时,我需要获取数据库实例组合框的内容并在调用中使用它来获取该实例中的所有数据库。我正在使用 RelayCommand (ICommand) 进行操作。按钮的操作正在正确设置。我在 DBInstance 类中有一个 SelectedDatabase 方法,但是当我单击按钮时它为空。
在 LoadDBInfo 方法中,selectedItem 参数为空。
这是我的 XAML:
<ComboBox x:Name="cbxRLFDBInstances" ItemsSource="{Binding DBInstances}"
SelectedValue="{Binding SelectedDBInstance}" SelectedValuePath="value"
HorizontalAlignment="Left" Height="28" Margin="189,87,0,0" VerticalAlignment="Top"
Width="250" FontFamily="Arial" FontSize="14.667"
IsEditable="True"/>
<Button x:Name="btnRLFDBLoadDBInfo" Content="Load DB Info" Command="{Binding LoadDBInfoCommand}"
CommandParameter="{Binding SelectedDBInstance}" HorizontalAlignment="Left" Height="26" Margin="475,89,0,0" VerticalAlignment="Top"
Width="101" FontFamily="Arial" FontSize="14.667" Background="#FFE8F9FF"
ToolTip="Click here after choosing or typing in the datbase instance. This will populate the database list."/>
<ComboBox x:Name="cbxRLFDBName" HorizontalAlignment="Left" Height="28" Margin="189,132,0,0"
ItemsSource="{Binding DBDatabases}" SelectedValue="{Binding SelectedDBDatabase}"
SelectedValuePath="value" VerticalAlignment="Top" Width="250" FontFamily="Arial"
FontSize="14.667" IsEditable="True" IsReadOnly="True"
ToolTip="Once a database is choosen the table list will automatically be populated."/>
这是我的视图模型:
namespace DatabaseTest.ViewModel
{
class RLFDatabaseTableViewModel
{
Utilities dbtUtilities = new Utilities();
public RelayCommand LoadDBInfoCommand
{
get;
set;
}
public RLFDatabaseTableViewModel()
{
LoadDBInstances();
LoadDBInfoCommand = new RelayCommand(LoadDBInfo);
}
#region Database Instance
public IList<DBInstance> DBInstances
{
get;
set;
}
public void LoadDBInstances()
{
IList<DBInstance> dbInstances = nList<DBInstance>();
DataTable dt = SmoApplication.EnumAvailableSqlServers(false);
dbInstances.Add(new DBInstance { DBInstanceName = "fal-conversion\\mun2012ci" });
dbInstances.Add(new DBInstance { DBInstanceName = "fal-conversion\\mun2014ci" });
if (dt.Rows.Count > 0)
{
foreach (DataRow dr in dt.Rows)
{
dbInstances.Add(new DBInstance { DBInstanceName = dr["Name"].ToString() });
}
}
DBInstances = dbInstances;
}
#endregion Database Instance
#region Database Names
public IList<DBDatabase> DBDatabases
{
get;
set;
}
public void LoadDBDatabases()
{
IList<DBDatabase> dbDatabases = new List<DBDatabase>();
dbDatabases.Add(new DBDatabase { DBDatabaseName = "DB - A" });
dbDatabases.Add(new DBDatabase { DBDatabaseName = "DB - B" });
DBDatabases = dbDatabases;
}
#endregion Database Names
#region Button Cammands
void LoadDBInfo(object selectedItem)
{
SqlConnection sqlConn = null;
IList<DBDatabase> dbDatabaseNames = new List<DBDatabase>();
// string selectedItem = dbInstances.
//Setting the PUBLIC property 'TestText', so PropertyChanged event is fired
if (selectedItem == null)
dbDatabaseNames = null;
else
{
SelectedDBInstance = selectedItem as DBInstance;
dbDatabaseNames = dbtUtilities.GetDBNames(sqlConn, _selectedDBInstance.ToString(),
_selectedDBDatabase.ToString());
}
DBDatabases = dbDatabaseNames;
}
#endregion Button Commands
}
这是我的模型:
namespace DatabaseTest.Model
{
public class RLFDatabaseTableModel { }
public class DBInstance : INotifyPropertyChanged
{
private string strDBInstance;
public override string ToString()
{
return strDBInstance;
}
public string DBInstanceName
{
get
{
return strDBInstance;
}
set
{
if (strDBInstance != value)
{
strDBInstance = value;
RaisePropertyChanged("DBInstanceName");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
public class DBDatabase : INotifyPropertyChanged
{
private string strDBDatabase;
public override string ToString()
{
return strDBDatabase;
}
public string DBDatabaseName
{
get
{
return strDBDatabase;
}
set
{
if (strDBDatabase != value)
{
strDBDatabase = value;
RaisePropertyChanged("DBDatabaseName");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
}
编辑:这是我加载第二个组合框 cbxRLFDBName 的代码,DBDatabase 具有值但未加载组合框。
public void LoadDatabases(string strDBInstanceName)
{
string strQuery;
IList<DBDatabase> dbDatabases = new List<DBDatabase>();
SqlConnection sqlUtilDBConn = null;
try
{
if (sqlUtilDBConn != null)
{
sqlUtilDBConn.Close();
}
sqlUtilDBConn = dbtUtilities.LoginToDatabase(strDBInstanceName, "master");
strQuery = "select name from sys.databases order by 1";
using (SqlCommand sqlCmd = new SqlCommand(strQuery, sqlUtilDBConn))
{
SqlDataReader sqlDataRead = sqlCmd.ExecuteReader();
while (sqlDataRead.Read())
{
string strDBNme = sqlDataRead.GetString(0);
dbDatabases.Add(new DBDatabase { DBDatabaseName = strDBNme });
}
sqlDataRead.Close();
sqlCmd.Dispose();
}
}
catch (Exception exQuery)
{
string strMsg;
strMsg = "GetNumRows: Error, '" + exQuery.Message + "', has occurred.";
System.Windows.MessageBox.Show(strMsg);
}
DBDatabases = dbDatabases;
}
编辑:我删除了一些不需要的代码,希望这会更容易阅读。我的问题是带有 ItemsSource="{Binding DBInstances}" 的组合框 "cbxRLFDBInstances" 可以很好地加载组合框。我还有另一个组合框,“ cbxRLFDBName”和ItemsSource =“ {Binding DBDatabases}”。当我选择合适的数据库实例并单击 Load DB Info 按钮时,LoadDatabases 运行,我可以看到 DBDatabases 中包含所需的信息。但是组合框没有加载,我没有失败。为什么一个 ItemsSource 数据绑定有效而另一个无效?我相信我正确设置了类,但似乎绑定没有发生?我错过了什么?
您的代码对我来说看起来不错,除了SelectedValuePath="value"
ComboBox 上的 。SelectedValuePath
指定要绑定到 的所选项目的属性SelectedValue
。SelectedDBInstance
是类型DBInstance
和DBInstance
类没有定义value
属性,所以我想说你只需SelectedValuePath="value"
要从 ComboBoxes 中删除。
编辑:
您需要您的 ViewModel 来实现INotifyPropertyChanged
:
class RLFDatabaseTableViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
// the rest of RLFDatabaseTableViewModel implementation ...
}
然后每次更改 ViewModel 内部的属性值时,也需要在RaisePropertyChanged
之后立即调用。例如:
DBDatabases = dbDatabaseNames;
RaisePropertyChanged("DBDatabases");
像这样定义属性很有帮助:
public string StringProperty
{
get { return this.stringProperty; }
set {
this.stringProperty = value;
this.RaisePropertyChanged("StringProperty");
}
}
private string stringProperty;
然后你就可以写
this.StringProperty = "new value";
并且将设置新值并发送更改通知。
您必须发送通知,因为 View (XAML) 和 ViewModel 是不同的类,并且 View 无法知道 ViewModel 上的属性已更改。如果 ViewModel 实现了INotifyPropertyChanged
,WPF 将通过PropertyChanged
事件监听属性更改并相应地更新视图。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句