我刚刚开始WPF,有点迷茫。
XAML 代码:
<DataGrid Name="dgResults" AutoGenerateColumns="True" ItemsSource="{Binding}">
</DataGrid>
C# 代码:
private void GetServices(string strComputer)
{
ManagementScope scope = new ManagementScope(@"\" + strComputer + @"rootcimv2");
SelectQuery query = new SelectQuery("Select * From Win32_Service");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection services = searcher.Get();
dgResults.ItemsSource = services;
}
我期望 WMI Win32_Service查询会将 WMI 属性显示为标头,并且返回集合中的每个对象将显示为一行。 但它显示的是 ManagementObjectCollection 属性。 有没有办法转换它并仍然允许所有属性可访问?
任何帮助将不胜感激。
这是一件有点棘手的事情。
首先,由于您不想显示ManagementBaseObject
实例的 CLR 属性,因此必须使用类型描述符概念来告知绑定引擎您具有自定义属性集。以下是您需要CustomTypeDescriptor
和PropertyDescriptor
的后代:
internal sealed class ManagementObjectPropertDescriptor : PropertyDescriptor
{
private readonly PropertyData propertyData;
public ManagementObjectPropertDescriptor(PropertyData propertyData)
: base(propertyData.Name, null)
{
this.propertyData = propertyData;
}
public override bool CanResetValue(object component)
{
return false;
}
public override Type ComponentType
{
get { return typeof(ManagementObjectTypeDescriptor); }
}
public override object GetValue(object component)
{
return propertyData.Value;
}
public override bool IsReadOnly
{
get { return true; }
}
public override Type PropertyType
{
get { return propertyData.Value != null ? propertyData.Value.GetType() : typeof(object); }
}
public override void ResetValue(object component)
{
}
public override void SetValue(object component, object value)
{
}
public override bool ShouldSerializeValue(object component)
{
return false;
}
}
public sealed class ManagementObjectTypeDescriptor : CustomTypeDescriptor
{
private PropertyData[] managementObjectProperties;
public ManagementObjectTypeDescriptor(ManagementBaseObject source)
{
this.managementObjectProperties = source
.Properties
.Cast<PropertyData>()
.ToArray();
}
public override PropertyDescriptorCollection GetProperties()
{
return new PropertyDescriptorCollection(managementObjectProperties
.Select(p => new ManagementObjectPropertDescriptor(p))
.ToArray());
}
}
为简单起见,属性设置为只读。
接下来,您需要将ManagementObjectCollection
转换为ManagementObjectTypeDescriptor
集合:
ManagementScope scope = new ManagementScope(@"\" + strComputer + @"rootcimv2");
SelectQuery query = new SelectQuery("Select * From Win32_Service");
var typeDescriptors = new ObservableCollection<ManagementObjectTypeDescriptor>();
using (var searcher = new ManagementObjectSearcher(scope, query))
{
using (var managementObjects = searcher.Get())
{
foreach (ManagementBaseObject managementObject in managementObjects)
{
using (managementObject)
{
typeDescriptors.Add(new ManagementObjectTypeDescriptor(managementObject));
}
}
}
}
dgResults.ItemsSource = new ArrayList(typeDescriptors);
请注意,ItemsSource
是 IList
的非泛型实现。从我的角度来看,DataGrid
有一个错误的行为:如果你将一个通用IList<ManagementObjectTypeDescriptor>
设置为项目源,DG
只会忽略从CustomTypeDescriptor
继承的事实,并且你会看到网格中根本没有列。同时,非泛型IList
按预期工作。