Соглашения о присвоении имен предлагают преимущество сообщения Вам что-то об объекте перед использованием его. Соглашения о присвоении имен широко много лет использовались, идя полностью назад в настойчивость Фортрана, что целочисленные значения были ограничены (если я помню правильно) к именам переменной как "i" и "j".
нотация Hungariation взяла соглашения о присвоении имен к совершенно новому ужасному уровню tha, описал тип переменной, было ли это указателем и т.д. Многие из нас, кто был представлен большому количеству кода с Венгерской записью, разработали нервные подергивания и словесные задержки.
имена интерфейса Добавления префикса с я относительно низкое влияние, безопасный способ определить тот объект.
@Pedery & jmayor: Спасибо за предложения, ребята! (см. мои выводы ниже)
После нескольких экспериментов, проб и ошибок, а также небольшого количества «отражений» мне удалось точно выяснить, почему я получаю загадочное сообщение об ошибке «Ошибка HRESULT E_FAIL возвращена. от вызова COM-компонента ».
Это произошло из-за того, что при перетаскивании данных WPF <-> Winforms в том же приложении данные должны быть сериализуемыми!
I ' Я проверил, насколько сложно будет преобразовать все наши классы в "сериализуемые", и это было бы настоящей проблемой по нескольким причинам ... во-первых, нам нужно было бы практически сделать все классы сериализуемыми, а во-вторых, некоторые этих классов есть ссылки на Controls! И элементы управления не сериализуемы. Таким образом, потребовался бы серьезный рефакторинг.
Итак ... поскольку мы хотели передать любой объект любого класса для перетаскивания из / в WPF внутри одного и того же приложения, я решил создать класс-оболочку с атрибутом Serializable и реализовать ISerializable. У меня будет 1 конструктор с 1 параметром типа «объект», который будет фактическими данными перетаскивания. Эта оболочка при сериализации / десериализации будет сериализовать не сам объект ... а, скорее, IntPtr для объекта (что мы можем сделать, поскольку нам нужна только эта функциональность внутри нашего приложения, содержащего только 1 экземпляр). См. Пример кода ниже:
[Serializable]
public class DataContainer : ISerializable
{
public object Data { get; set; }
public DataContainer(object data)
{
Data = data;
}
// Deserialization constructor
protected DataContainer(SerializationInfo info, StreamingContext context)
{
IntPtr address = (IntPtr)info.GetValue("dataAddress", typeof(IntPtr));
GCHandle handle = GCHandle.FromIntPtr(address);
Data = handle.Target;
handle.Free();
}
#region ISerializable Members
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
GCHandle handle = GCHandle.Alloc(Data);
IntPtr address = GCHandle.ToIntPtr(handle);
info.AddValue("dataAddress", address);
}
#endregion
}
Чтобы сохранить функциональность IDataObject, я создал следующую оболочку DataObject:
public class DataObject : IDataObject
{
System.Collections.Hashtable _Data = new System.Collections.Hashtable();
public DataObject() { }
public DataObject(object data)
{
SetData(data);
}
public DataObject(string format, object data)
{
SetData(format, data);
}
#region IDataObject Members
public object GetData(Type format)
{
return _Data[format.FullName];
}
public bool GetDataPresent(Type format)
{
return _Data.ContainsKey(format.FullName);
}
public string[] GetFormats()
{
string[] strArray = new string[_Data.Keys.Count];
_Data.Keys.CopyTo(strArray, 0);
return strArray;
}
public string[] GetFormats(bool autoConvert)
{
return GetFormats();
}
private void SetData(object data, string format)
{
object obj = new DataContainer(data);
if (string.IsNullOrEmpty(format))
{
// Create a dummy DataObject object to retrieve all possible formats.
// Ex.: For a System.String type, GetFormats returns 3 formats:
// "System.String", "UnicodeText" and "Text"
System.Windows.Forms.DataObject dataObject = new System.Windows.Forms.DataObject(data);
foreach (string fmt in dataObject.GetFormats())
{
_Data[fmt] = obj;
}
}
else
{
_Data[format] = obj;
}
}
public void SetData(object data)
{
SetData(data, null);
}
#endregion
}
И мы используем вышеуказанные классы следующим образом:
myControl.DoDragDrop(new MyNamespace.DataObject(myNonSerializableObject));
// in the drop event for example
e.Data.GetData(typeof(myNonSerializableClass));
Я знаю, я знаю ... это не очень красиво . .. но он делает то, что мы хотели. Мы также создали вспомогательный класс перетаскивания, который маскирует создание DataObject и имеет шаблонные функции GetData для извлечения данных без каких-либо преобразований ... примерно так:
myNonSerializableClass newObj = DragDropHelper.GetData<myNonSerializableClass>(e.Data);
Так что еще раз спасибо за ответы! Ребята, вы дали мне хорошие идеи, где искать возможные решения!
-Oli
Некоторое время назад у меня была «похожая» проблема, поэтому я могу хотя бы рассказать вам то, что обнаружил.
Похоже .Net прибегает к удаленному взаимодействию OLE, когда выполняются операции перетаскивания. выполняется в простейших случаях. По какой-то причине GetDataPresent в этих случаях будет успешным, а GetData - нет. Кроме того, это загадочно из-за того, что существует несколько версий IDataObject в структуре .Net.
Windows Forms по умолчанию использует System.Windows.Forms.IDataObject. Однако в вашем случае вы можете попробовать дать System.Runtime.InteropServices.ComTypes.IDataObject вместо этого выстрел. Вы также можете посмотреть мое обсуждение здесь .
Надеюсь, это поможет.
Может, все наоборот. PreviewDragEnter должен быть связан с WPFTextBox. Также обратите внимание на класс DragEventArgs. Один находится в System.Windows.Form (версия Windows Form), а другой - в System.Windows (для версии WPF).