Попробуйте использовать Observable Collection
вместо обычного списка.Эта коллекция уже реализует INotifyCollectionChanged.
Обратите внимание, что это будет работать для добавления или удаления элементов в списке, но если вы сами измените свойства элемента и захотите обновить ObservableCollection
, вам необходимо иметь ObservableCollection
of ViewModels
, которые реализуют INotifyPropertyChanged
для каждого свойства.
EDIT
Это может быть глупый вопрос, но где вы на самом деле вызываете этот метод x?Я почти точно скопировал ваш код, создал свой собственный класс Result, реализовал INotifyPropertyChanged и создал реализацию шаблона RelayCommand , привязав это к команде кнопки, и все заработало.Когда я нажимаю кнопку, сетка данных изменяется.
Все, что я могу думать, - это то, что вы на самом деле не реализовали INotifyPropertyChanged или не используете метод x.
здеськод, который я сделал:
public class Model : INotifyPropertyChanged
{
ObservableCollection<Result> _results = new ObservableCollection<Result>();
private List<string> Files;
public void X()
{
foreach (var file in Files)
{
_results.Add(new Result() { File = file, Status = "passsed" });
}
_results.Add(new Result() { File = DateTime.Now.ToString(), Status = "passed" });
}
public ObservableCollection<Result> Results
{
get { return _results; }
set { _results = value; OnPropertyChanged("Results"); }
}
public ICommand XCmd { get; protected set; }
private void InitializeCommands()
{
this.XCmd = new RelayCommand((param) => { this.X(); },
(param) => { return true; });
}
public Model()
{
Files = new List<string>();
Files.Add("ONE");
Files.Add("TWO");
Files.Add("THREE");
Files.Add("FOUR");
_results.Add(new Result() { File = "ZERO", Status = "Pending" });
_results.Add(new Result() { File = DateTime.Now.ToString(), Status = "Pending" });
InitializeCommands();
}
#region INotifyPropertyChanged Members
/// <summary>
/// Raised when a property on this object has a new value.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Raises this object's PropertyChanged event.
/// </summary>
/// <param name="propertyName">The property that has a new value.</param>
protected virtual void OnPropertyChanged(string propertyName)
{
this.VerifyPropertyName(propertyName);
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
#endregion // INotifyPropertyChanged Members
#region Debugging Aides
/// <summary>
/// Warns the developer if this object does not have
/// a public property with the specified name. This
/// method does not exist in a Release build.
/// </summary>
[Conditional("DEBUG")]
[DebuggerStepThrough]
public void VerifyPropertyName(string propertyName)
{
// Verify that the property name matches a real,
// public, instance property on this object.
if (TypeDescriptor.GetProperties(this)[propertyName] == null)
{
string msg = "Invalid property name: " + propertyName;
if (this.ThrowOnInvalidPropertyName)
throw new Exception(msg);
else
Debug.Fail(msg);
}
}
/// <summary>
/// Returns whether an exception is thrown, or if a Debug.Fail() is used
/// when an invalid property name is passed to the VerifyPropertyName method.
/// The default value is false, but subclasses used by unit tests might
/// override this property's getter to return true.
/// </summary>
protected virtual bool ThrowOnInvalidPropertyName { get; private set; }
#endregion // Debugging Aides
Обратите внимание, что область членов INotifyPropertyChanged реализует событие PropertyChanged, а область вспомогательных средств отладки просто проверяет, действительно ли существует свойство, указанное в обработчике OnPropertyChanged.
Вот xaml:
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<DataGrid
HorizontalAlignment="Stretch"
Name="resultDataGrid"
VerticalAlignment="Stretch"
ItemsSource="{Binding Path=Results, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
/>
<Button Grid.Row="2" Command="{Binding XCmd}" Margin="5,5,5,5">click</Button>
</Grid>
Это не красиво, я знаю, но вы можете стилизовать его как угодно
А вот реализация relaycommand, с которой я связал вас ранее:
public class RelayCommand : ICommand
{
#region Private Accessor Fields
/// <summary>
/// A boolean function that contains the code to enable/disable the command and the associated UI elements.
/// </summary>
private readonly Func<object, bool> _canExecute = null;
/// <summary>
/// A generic delegate that will contain the code to execute.
/// </summary>
private readonly Action<object> _executeAction = null;
#endregion //Private Accessor Fields
#region Constructor
/// <summary>
/// Initializes a new instance of the RelayCommannd class
/// </summary>
/// <param name="executeAction">The execute action.</param>
/// <param name="canExecute">The can execute.</param>
public RelayCommand(Action<object> executeAction, Func<object, bool> canExecute)
{
this._executeAction = executeAction;
this._canExecute = canExecute;
}
#endregion
//Modified on 15 August 2011. CanExecuteChanged
#region Implementation of ICommand
/// <summary>
/// Occurs when changes occur that affect whether or not the command should execute.
/// </summary>
public event EventHandler CanExecuteChanged
{
//RequerySuggested occurs when the CommandManager detects conditions that might
//change the ability of a command to execute.
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
/// <summary>
/// Defines the method that determines whether the command can execute in its current state.
/// </summary>
/// <param name="parameter">Data used by the command. If the command does not require data to be passed,
/// this object can be null.</param>
/// <returns>true if this command can be executed; otherwise, false.</returns>
public bool CanExecute(object parameter)
{
if (this._canExecute == null)
{
return true;
}
return this._canExecute(parameter);
}
/// <summary>
/// Defines the method to be called when the command is invoked.
/// </summary>
/// <param name="parameter">Data used by the command. If the command does not require data to be passed,
/// this object can be set to null</param>
public void Execute(object parameter)
{
if (this._executeAction != null)
{
this._executeAction(parameter);
}
}
#endregion
Если это не сработает, вам придется показать мне больше вашего кода, потому что я действительно не знаю, почему он не работает.