【问题标题】:How do you display a WMI Collection to a WPF DataGrid如何将 WMI 集合显示到 WPF DataGrid
【发布时间】:2014-01-13 05:28:33
【问题描述】:

我刚开始 WPF,有点迷茫。

XAML 代码:

<DataGrid  Name="dgResults" AutoGenerateColumns="True" ItemsSource="{Binding}">
</DataGrid>

C#代码:

private void GetServices(string strComputer)
{
     ManagementScope scope = new ManagementScope(@"\\" + strComputer + @"\root\cimv2");
     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 属性。有没有办法转换它并仍然允许访问所有属性?

任何帮助将不胜感激。

【问题讨论】:

  • 此代码显示ManagementObject 属性。这里的“属性”是指 CLR 属性,而不是 WMI 属性 (msdn.microsoft.com/en-us/library/…)。此外,创建 WMI 对象并忘记它们是一个坏主意 - ManagementObjectSearcherManagementObjectCollection 和每个将通过集合枚举的 ManagementBaseObject 都是 IDisposable 并且必须被处置。
  • 很好,丹尼斯。我还不习惯 c#。我通常在 vbs、批处理中编写我的应用程序脚本。我要么采用编译器调用 dispose 的 using 语句,要么在 try 或 finally 块中手动调用 dispose 方法。

标签: c# wpf xaml datagrid wmi


【解决方案1】:

这有点棘手。

首先,由于您不想显示 ManagementBaseObject 实例的 CLR 属性,因此您必须使用类型描述符概念来告诉绑定引擎,您有自定义属性。以下是您需要的 CustomTypeDescriptorPropertyDescriptor 的后代:

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 + @"\root\cimv2");
        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);

请注意,ItemsSourceIList 的非泛型实现。 DataGrid 有一个错误,从我的观点来看,这里的行为:如果你将一个通用的IList&lt;ManagementObjectTypeDescriptor&gt; 设置为项目源,DG 将忽略从CustomTypeDescriptor 继承的事实,你会看到网格中根本没有列。同时,非泛型 IList 按预期工作。

【讨论】:

  • 您确定这些是 DG 列,可能是,您正在应用任何自定义样式吗?在具有默认样式的空 WPF 应用程序中,我有第一列“AcceptPause”和最后一列“WaitHint”。没有任何空列。
  • 我可能误解了 DataGrid 的样式和自动填充属性。我通过修改 SelectQuery 只显示 2 列。其余的是空白空间,列/行边界看起来只是另一列。看起来我需要修改我的 XAML 参数以自动正确调整宽度并将 AutoSize 调整为内容。我假设与 ArrayList(typeDescriptors) 数组交互会让我附加我自己的自定义列,比如行索引?
  • @Mark: 没错,只要修改GetProperties 以返回适当的PropertyDescriptor 后代,您将在DG 中获得自定义属性和相应的列。
猜你喜欢
  • 2012-05-10
  • 2023-03-07
  • 2012-07-07
  • 1970-01-01
  • 2014-10-05
  • 2011-06-13
  • 2017-04-18
  • 2014-04-18
  • 1970-01-01
相关资源
最近更新 更多