Я пытаюсь добиться двустороннего связывания между DataGridView и BindingList, который предоставляет данные для DGV. Некоторые столбцы еще не отражают изменения в базовом списке, и я думаю, что это потому, что я не предоставил установщик (и) свойств для уведомления об изменениях свойств. Вместо того, чтобы кодировать установщик для свойства Rows так же, как я делал для свойства Process, я пытаюсь стать более «элегантным» и понимаю, что застрял ....
Я наткнулся на очень интересную рецензию для более элегантного подхода и пытаюсь реализовать ее концепции (см. Пожалуйста):
http://www.gavaghan.org/blog/2007/07/17/use-inotifypropertychanged-with-bindinglist/
Вот код из статьи Майка, которую я хочу использовать (установлен как Utilities.cs в моем проекте CBMI.Common):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
namespace CBMI.Common
{
public static class Utilities
{
public static bool Set<T>(object owner, string propName,
ref T oldValue, T newValue, PropertyChangedEventHandler eventHandler)
{
// make sure the property name really exists
if (owner.GetType().GetProperty(propName) == null)
{
throw new ArgumentException("No property named '" + propName + "' on " + owner.GetType().FullName);
}
if (!Equals(oldValue, newValue)) // we only raise an event if the value has changed
{
oldValue = newValue;
if (eventHandler != null)
{
eventHandler(owner, new PropertyChangedEventArgs(propName));
}
}
return true; // Please NOTE: I had to add this statement to avoid compile error:
// "not all code paths return a value".
}
}
}
Итак, мой ПЕРВЫЙ ВОПРОС об этом: у автора в его статье не было оператора return , и я добавил его, что устранило ошибку компилятора. Я предполагаю, что eventHandler выполняется и возвращается, и это было упущение автора, и это должно вернуть true, так как метод хочет тип возврата bool. Это правильное предположение?
Мой 2-й ВОПРОС показывает, какой я новичок в C #, когда пытаюсь использовать этот вспомогательный метод выше. Я закодировал этот класс в отдельный файл с именем InputFileInfo.cs в том же проекте (и пространстве имен), что и выше:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
namespace CBMI.Common
{
public class InputFileInfo : INotifyPropertyChanged
{
private bool processThisFile;
public bool Process
{
get { return processThisFile; }
set
{
processThisFile = value;
this.NotifyPropertyChanged("Process");
}
}
public string FileName { get; set; }
private long rowsReturned;
public long Rows
{
get { return rowsReturned; }
set
{
Utilities.Set(this, "Rows", ref rowsReturned, value, PropertyChanged);
}
}
public string Message { get; set; }
// constructor
public InputFileInfo(string fName)
{
Process = true;
FileName = fName;
Rows = 0;
Message = String.Empty;
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string name)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}
Сеттер для второго свойства в этом классе - это место, где я пытаюсь использовать статический метод Майка:
Utilities.Set(this, "Rows", ref rowsReturned, value, PropertyChanged);
Если я удаляю Utilities.Set и просто кодирую его следующим образом:
Set(this, "Rows", ref rowsReturned, value, PropertyChanged);
.. тогда я получаю компилятор с жалобой, что "имя 'Set' не существует в текущем контексте" .
Я попытался добавить с помощью утилит; директива но это не решило проблему.
Наконец, я не понимаю параметры: ref T oldValue, T newValue
ни параметр с именем значение , где вызывается метод Set.
Может кто-нибудь помочь мне разобраться с этими многочисленными заблуждениями относительно этого кода, чтобы я мог использовать эти более продвинутые идеи?
---- РЕДАКТИРОВАТЬ ОБНОВЛЕНИЕ ----
Два хороших ответа помогли мне получить эту работу. "Второй вопрос" в оригинальном посте выше остается немного неуловимым. Добавлены комментарии для каждого запроса «наилучшей практики» о том, как упаковать это, чтобы я мог использовать простой синтаксис вызова, как в оригинальной статье Майка. То есть я пытаюсь вызвать "вспомогательные" статические методы только по имени метода. Я хочу понять, как вызвать как:
set
{
Set(this, "Rows", ref rowsReturned, value, PropertyChanged);
}
вместо того, чтобы кодировать как:
set
{
Utilities.Set(this, "Rows", ref rowsReturned, value, PropertyChanged);
}
Я получил это с помощью кодирования Utilities.Set, но я предполагаю, что вопрос немного превращается в - "Где я могу поместить статические методы и как их вызывать, чтобы мне не нужно было" квалифицировать " их с именем класса? " Я хотел бы понять, как упаковать обычно полезные методы типа" утилиты ", которые не требуют экземпляра объекта. В этом случае статический метод называется Set, но я хотел бы иметь возможность добавлять другие статические методы, такие как:
public static int HelpfulMethodXXXX(string s, int num)
У меня есть отдельно скомпилированная DLL (проект Vstudio), содержащая только файлы классов. В конечном счете, я хотел бы думать, что я мог бы использовать этот класс в других приложениях.
Где лучшее место для объявления таких статических методов, чтобы их можно было вызывать как:
int i = HelpfulMethodXXXX("Sample", testNumber);
вместо:
int i = ContainingClassName.HelpfulMethodXXXX("Sample", testNumber);