我有一个将Windows.Form与Infragistics一起用于GUI / UI的应用程序。我想从我的主项目中分离出诸如BackColor,ForeColor等属性的分配,以使其更美观,更小巧。所以我在VS(2017,Professional)中创建了一个新项目,在其中使用反射设置了所有属性,因为我想避免在GUI项目中引用主项目。
我得到了要更改的控件元素,如下所示:
object controlsCollectionObject = currentObject.GetType().GetProperty("Controls").GetValue(currentObject);
ArrayList controlsInnerList = controlsCollectionObject.GetType().GetProperty("InnerList", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(controlsCollectionObject) as ArrayList;
此InnerList包含该ControlCollection对象的控件元素。 然后,我遍历此列表并查找要设置的两个属性:
Type listItemType = listItem.GetType();
if (wantedControls.Contains(listItem.GetType().Name))
{
listItemName.Append(listItemType.GetProperty("Name").GetValue(listItem) as string);
if (!controlElements.ContainsKey(listItemName.ToString()))
{
controlElements.Add(listItemName.ToString(), new Tuple<object, PropertyInfo>(listItem, listItemType.GetProperty("BackColor")));
}
if (listItemType.GetProperty("Appearance") != null)
{
appearanceObject = listItemType.GetProperty("Appearance").GetValue(listItem);
listItemName.Append("_Appearance");
controlElements.Add(listItemName.ToString(), new Tuple<object, PropertyInfo>(appearanceObject, appearanceObject.GetType().GetProperty("BackColor")));
}
if (!doNotPushInStack.Contains(listItem.GetType().Name))
{
objectsToIterate.Push(listItem);
}
listItemName.Clear();
}
其中controlElements
是Dictionary<string, Tuple<object, PropertyInfo>>
,而wantedControls
是包含我要查找和更改的所有控制对象类型的字符串数组。
objectsToIterate
是我用来避免递归的Stack<object>
,因为我也想搜索某些控件以检查它们是否包含我可能要更改的其他控件。
然后,我像这样设置属性:
private static void SetControlProperties()
{
Tuple<object,PropertyInfo> objectReferenceAndBackColor;
DataRow dbPanels;
for (int i = 0; i < panelsData.Length; i++)
{
dbPanels = panelsData[i];
if(controlElements.TryGetValue(dbPanels["ButtonText"].ToString(), out objectReferenceAndBackColor))
{
objectReferenceAndBackColor.Item2.SetValue(objectReferenceAndBackColor.Item1, Color.FromName(dbPanels["BackColor1"].ToString()));
Debug.WriteLine(objectReferenceAndBackColor.Item2.GetValue(objectReferenceAndBackColor.Item1).ToString() + " I am Object of: " + objectReferenceAndBackColor.Item1.ToString());
}
}
}
panelsData
是DataRow
,其中包含我要写入属性中的所有值。所有值都保存在本地SQL数据库中。
我检查["ButtonText"]
的原因是因为我将控件的数据集临时写入了“按钮”数据表
对于大多数组件(例如面板),它都可以正常工作,但是某些基础设施组件(例如,UltraTextEditor)不起作用。它似乎没有注册或接管我通过反射通过SetValue()设置的更改。
当我检查主项目中是否设置了值之后,我看到某些组件没有保存这些值:
Color [Transparent] I am Object of: Infragistics.Win.UltraWinEditors.UltraTextEditor
相反,它在日志中应如下所示:
Color [255; 11; 110; 143] I am Object of: Infragistics.Win.UltraWinGrid.UltraGrid
我尝试设置的值不是readOnly。 UltraTextEditor.UseAppStyling
和UseOsThemes
属性都设置为false。我还检查了我的值是否在某个时候被覆盖,但事实并非如此。我使用了我在主项目中显示的相同方法,以查看这是否是权限问题,但这也不起作用。
我可以在主项目中通过简单地使用ultryTextEditorTest.BackColor = Color.Blue;
来设置这些组件的背景色,但是通过反射它不会将其写入属性。我已经检查了代码中来自数据库和sql查询的值,看是否出错了,但是一切都正确,所以现在我不确定是什么问题,或者至少不知道为什么它不能让我设置背景色通过反射。
我知道我可以正常设置颜色,但此时我很固执,想知道为什么它不起作用,或者是否可能无法这样做,因为基础设施禁止我这样做。也就是说,如果问题出在基础设施上,或者我在代码中犯了一个看不见的错误。
如果让我知道,我希望这不是一次,而且我会尝试将其分解一些,以便于阅读和理解。
非常感谢您的帮助。