[英]How to highlight a row and force row/cell refresh in a WPF DataGrid?
[英]WPF Datagrid: Force Refresh
我有以下過程:
那么如何強制刷新數據網格內容呢?
嘗試以下:
這是一些示例代碼:
首先是數據庫處理程序,它處理視圖模型和數據庫之間的數據交換。 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綁定到了視圖模型中的名稱的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>
使用ICollectionView-將您的Datagrid綁定到它-每當您想刷新Datagrid時在Viewmodel中調用.Refresh()
刪除大部分DBHandler
, DBHandler
您感到困惑。 您要做的就是在請求時檢索數據庫內容,並在收到提示時將其保存。 它坐在那里等待MainWindowViewModel
訂單。 主視圖模型始終負責。 它使用模型(即DBHandler
)來存儲和檢索信息,並在其屬性中公開這些信息。 它還公開了命令。 視圖是用戶觀察視圖模型並與之對話的方式。 viewmodel不知道該視圖存在。 它所知道的是, 某個處於黑暗中的人偶爾會在其屬性上調用吸氣劑和塞特方法,或者在其命令之一上調用Execute
。
為MainWindowViewModel提供一個名為ObservableCollection<String>
的公共Names
屬性。 將其綁定到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
,但是我推斷它可以正常工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.