我有以下过程:
那么如何强制刷新datagrid内容?
尝试以下:
以下是一些示例代码:
首先是数据库处理程序,它处理视图模型和数据库之间的数据交换。 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
}
最后一个视图包含一个名称的TextBox,它将通过按钮单击保存,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>
答案 0 :(得分:0)
使用ICollectionView - 将Datagrid绑定到它 - 并且只要你想刷新Datagrid就在Viewmodel中调用.Refresh()
答案 1 :(得分:0)
删除大多数DBHandler
,这只是让您感到困惑。您要做的就是在请求时检索数据库内容,并在被告知时保存。它坐在那里等待MainWindowViewModel
的订单。主视图模型始终处于负责状态。它使用模型(即DBHandler
)来存储和检索它在其属性中公开的信息。它还暴露命令。视图是用户如何观察视图模型并与之对话。视图模型不知道视图存在。它只知道在黑暗中某人偶尔会在其属性上调用getter和setter,或者在其中一个命令上调用Execute
。
为MainWindowViewModel提供一个公共Names
属性ObservableCollection<String>
。将它绑定到DataGrid或UI中的任何内容。如果您有可能添加或删除其中的项目,请不要在视图模型中使用List<T>
。
编写一个名为DelegateCommand
的新Command类,如下所示:
public class DelegateCommand<T> : ICommand
{
public DelegateCommand(Action<T> action, Func<T, bool> canExecute = null)
{
_action = action;
_canExecute = canExecute;
}
private Action<T> _action;
private Func<T, bool> _canExecute;
public event EventHandler CanExecuteChanged;
public void RaiseCanExecuteChanged()
{
var handler = CanExecuteChanged;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
public bool CanExecute(object parameter)
{
if (_canExecute != null)
{
return _canExecute((T)parameter);
}
return true;
}
public void Execute(object parameter)
{
if (_action != null)
{
_action((T)parameter);
}
}
}
使用它:
public MainWindowViewModel()
{
// Initialize the command to add a name
_addNameCommand = new DelegateCommand<string>(DoAddName);
// Assign database collection entries
Names = new ObservableCollection<string>(DBHandler.GetInstance().Names);
}
public void DoAddName(String name)
{
Names.Add(name);
/*
Update database here
*/
}
ICommand _addName;
// Don't name anything "button" in your viewmodel; it's a bad habit to think
// that way. It's just a command. If the view wants to use a button to invoke
// it, that's the view's business. The viewmodel just makes stuff available.
public ICommand AddNameCommand
{
get {
Debug.WriteLine("getting AddNameCommand");
return _addNameCommand;
}
}
// Never, never, NEVER NEVER NEVER NEVER touch _names other than in the
// get and set blocks of Names.
// And make the set private. It should be kept in sync with the database, so
// don't let any other class but this one mess with it.
private ObservableCollection<string> _names = new ObservableCollection<string>();
public ObservableCollection<string> Names
{
get { return _names; }
private set {
if (_names != value)
{
_names = value;
NotifyPropertyChanged();
}
}
}
我不知道您将Names
绑定到DataGrid
的行为,但我推断它的工作正常。