【发布时间】:2017-05-09 12:47:41
【问题描述】:
我有以下流程:
- 在视图/视图模型中创建一个新对象并通过数据库处理程序将其保存在数据库中
- 数据库处理程序实现 INotifyProperyChanged。因此,在 1. 之后,数据库处理程序会通知其他视图模型有关更改。其中一个对应的视图包含一个绑定到存储在数据库中的 ObservableCollection 的数据网格。所以视图/视图模型主动访问数据库。
- 新对象的创建(参见 1.)会更改数据库内容,并且还应该更新数据网格视图。因此视图模型通过通知获知更改。因此,下一步将是再次访问数据库并使用这些新数据填充或更新 observable。
那么如何强制刷新datagrid内容呢?
尝试以下:
- 暂时将 ObservableCollection 分配为 null 不会刷新数据网格,因为它不会通知数据网格视图。
- 清除集合并将所有项目添加到新集合(可行,但听起来有点奇怪,因为在大多数情况下我只会将一个对象添加到数据库中)
这里是一些示例代码:
首先是数据库处理程序,它处理视图模型和数据库之间的数据交换。 DBHandler 实现 INotifyPropertyChanged 以限定视图模型以对数据库中的更改做出反应。目前 DBHandler 仅在名称列表发生更改时通知:
public class DBHandler:INotifyPropertyChanged
{
#region Singleton Pattern
private static DBHandler instance;
private DBHandler()
{
}
public static DBHandler GetInstance()
{
if (instance == null)
instance = new DBHandler();
return instance;
}
#endregion
#region INotifyPropertyChanged Implementation
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
// Represents Sample Data of the database
private List<string> names = new List<string>() { "Sample1", "Sample2" };
public List<string> Names
{
get { return names; }
}
/// <summary>
/// Saves a new name in the database
/// </summary>
/// <param name="name"></param>
public void AddNewName(string name)
{
names.Add(name);
NotifyPropertyChanged();
}
}
MainWindowViewModels可以通过DBHandler保存一个新名字,并通过监听List DBHandler.Names的变化
public class MainWindowViewModel
{
#region Constructors
public MainWindowViewModel()
{
// Initialize the command for the add button click
addName = new AddNameCommand();
// Assign database collection entries
names = new ObservableCollection<string>(DBHandler.GetInstance().Names);
DBHandler.GetInstance().PropertyChanged += MainWindowViewModel_PropertyChanged_Names;
}
/// <summary>
/// Listen for the DBHandler.Names change for updating the datagrid view.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MainWindowViewModel_PropertyChanged_Names(object sender, PropertyChangedEventArgs e)
{
if(e.PropertyName == "Names")
{
// Try to update the datagrid view
// First Try: Reassign
names = new ObservableCollection<string>(DBHandler.GetInstance().Names);
}
}
#endregion
private ObservableCollection<string> names;
public ObservableCollection<string> Names
{
get { return names; }
set { names = value; }
}
#region Commands
/// <summary>
/// Command for adding the textbox content as new name to the database
/// </summary>
public class AddNameCommand : ICommand
{
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
Debug.WriteLine("CanExecute");
return ((string)parameter) != "" || parameter != null;
}
public void Execute(object parameter)
{
// Save the name in the database
DBHandler.GetInstance().AddNewName((string)parameter);
}
}
AddNameCommand addName; // Instance of the command which will be intialized in the constructor
public ICommand btnClickAdd
{
get {
Debug.WriteLine("btnClickAdd");
return (ICommand) addName; }
}
#endregion
}
最后一个视图包含一个文本框,用于保存通过单击按钮保存的名称,以及一个用于显示数据库中所有名称的 DataGrid。因此,DataGrid 绑定到视图模型中的名称的 ObservableCollection。
<Window.Resources>
<local:MainWindowViewModel x:Key="ViewModel"/>
</Window.Resources>
<Grid>
<DataGrid x:Name="dataGrid" ItemsSource="{Binding Source={StaticResource ViewModel}, Path=Names}" HorizontalAlignment="Left" Margin="48,142,0,0" VerticalAlignment="Top" Height="127" Width="422"/>
<Button x:Name="button_AddName" Command="{Binding Source={StaticResource ViewModel}, Path=btnClickAdd}" Content="Add" HorizontalAlignment="Left" Margin="331,61,0,0" VerticalAlignment="Top" Width="75" CommandParameter="{Binding Text, ElementName=textBox_Name}"/>
<TextBox x:Name="textBox_Name" HorizontalAlignment="Left" Height="23" Margin="160,58,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/>
</Grid>
【问题讨论】:
-
向我们展示代码。没有人可以根据对您打算做什么的 50,000 英尺描述来猜测您的代码实际上在做什么。我需要: 1)您如何将集合放入网格中? 2)你是如何将新项目添加到集合中的?代码,代码,只有代码。如果您有一点解释任何东西的冲动,只需粘贴代码即可。
-
是的,添加了代码。
-
MainWindowViewModel应该实现INotifyPropertyChanged。 -
当您在
AddNewName()中调用NotifyPropertyChanged();时,您认为事件参数对于PropertyName会有什么影响?你有没有在MainWindowViewModel_PropertyChanged_Names中设置断点来了解那里到底发生了什么? -
你是对的。我过滤了 PropertyName,它是“AddNewName”。我从我的主要项目中复制了这个。在此更改和 INotifyPropertyChanged 的实施之后,它似乎工作正常。因此,我将搜索与我的主项目的差异,因为我还在视图模型中实现了 INotifyPropertyChanged,但它不起作用。