wpf PropertyGrid 显示List<string,class>

本文介绍了如何通过自定义TypeConverterMyListTypeConverter和PropertyDescriptor来让PropertyGrid支持List<class>类型的属性,包括StringListPropertyDescriptor和MyClassListPropertyDescriptor的实现,以及在Windows应用中的实际使用示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PropertyGrid默认情况下可以显示和修改List<string>类型的属性,但不支持List<class>类型。不过你可以通过自定义TypeConverter来扩展PropertyGrid的功能,使其支持显示和修改List<class>类型的属性。

以下是一个简单的示例:

public class MyListTypeConverter : TypeConverter
{
    public override bool GetPropertiesSupported(ITypeDescriptorContext context)
    {
        return true;
    }

    public override PropertyDescriptorCollection GetProperties(
        ITypeDescriptorContext context, 
        object value, 
        Attribute[] attributes)
    {
        var properties = new List<PropertyDescriptor>();

        if (value is List<string> stringList)
        {
            for (int i = 0; i < stringList.Count; i++)
            {
                properties.Add(new StringListPropertyDescriptor(stringList, i));
            }
        }
        else if (value is List<MyClass> myClassList)
        {
            for (int i = 0; i < myClassList.Count; i++)
            {
                properties.Add(new MyClassListPropertyDescriptor(myClassList, i));
            }
        }

        return new PropertyDescriptorCollection(properties.ToArray());
    }
}

public class StringListPropertyDescriptor : PropertyDescriptor
{
    private readonly List<string> _list;
    private readonly int _index;

    public StringListPropertyDescriptor(List<string> list, int index)
        : base("Item " + index, null)
    {
        _list = list;
        _index = index;
    }

    public override Type ComponentType => typeof(List<string>);
    public override bool IsReadOnly => false;
    public override Type PropertyType => typeof(string);

    public override object GetValue(object component)
    {
        return _list[_index];
    }

    public override void SetValue(object component, object value)
    {
        _list[_index] = (string)value;
    }
}

public class MyClassListPropertyDescriptor : PropertyDescriptor
{
    private readonly List<MyClass> _list;
    private readonly int _index;

    public MyClassListPropertyDescriptor(List<MyClass> list, int index)
        : base("Item " + index, null)
    {
        _list = list;
        _index = index;
    }

    public override Type ComponentType => typeof(List<MyClass>);
    public override bool IsReadOnly => false;
    public override Type PropertyType => typeof(MyClass);

    public override object GetValue(object component)
    {
        return _list[_index];
    }

    public override void SetValue(object component, object value)
    {
        _list[_index] = (MyClass)value;
    }

    public override PropertyDescriptorCollection GetChildProperties(
        object instance, 
        Attribute[] attributes)
    {
        var properties = TypeDescriptor.GetProperties(instance, attributes)
                                        .Cast<PropertyDescriptor>();

        return new PropertyDescriptorCollection(properties.ToArray());
    }
}

public class MyClass
{
    public string StringProperty { get; set; }
    public int IntProperty { get; set; }
}

public class MyViewModel
{
    [TypeConverter(typeof(MyListTypeConverter))]
    public List<string> StringList { get; set; }

    [TypeConverter(typeof(MyListTypeConverter))]
    public List<MyClass> MyClassList { get; set; }
}

在这个示例中,我们定义了两个自定义的PropertyDescriptor分别用于表示List<string>和List<MyClass>类型的属性。我们还定义了一个自定义的TypeConverter,用于选择哪种PropertyDescriptor应该用于特定的属性。

在MyClassListPropertyDescriptor中,我们还需要重写GetChildProperties方法,以便能够获取MyClass类型的属性。

最后,将MyViewModel对象作为PropertyGrid的SelectedObject即可:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        DataContext = new MyViewModel
        {
            StringList = new List<string> { "foo", "bar" },
            MyClassList = new List<MyClass>
            {
                new MyClass { StringProperty = "hello", IntProperty = 42 },
                new MyClass { StringProperty = "world", IntProperty = 123 }
            }
        };
    }
}

 

<Grid Grid.Column="1"> <DataGrid Grid.Row="1" x:Name="DetectDetail" IsReadOnly="True" AutoGenerateColumns="False" HeadersVisibility="None" RowHeaderWidth="0" ItemsSource="{Binding DetectData.DetailTable }" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" ScrollViewer.CanContentScroll="False" CanUserAddRows="False" Canvas.Right="0" IsHitTestVisible="True" GridLinesVisibility="None" BorderBrush="Transparent" Background="Transparent" > <DataGrid.RowStyle> <Style TargetType="{x:Type DataGridRow}"> <Setter Property="MinHeight" Value="40"/> <Setter Property="Background" Value="Transparent"/> <!--<Setter Property="BorderThickness" Value="10"/>--> <Setter Property="BorderBrush" Value="Transparent"/> </Style> </DataGrid.RowStyle> <DataGrid.CellStyle> <Style TargetType="{x:Type DataGridCell}"> <Setter Property="BorderThickness" Value="0"/> <Style.Triggers> <Trigger Property="IsSelected" Value="True"> <Setter Property="Background"> <!--值--> <Setter.Value> <!--色刷,Opacity:透明度--> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0" Opacity="0.2"> <GradientStop Color="#25EEF4" Offset="0"/> <GradientStop Color="#25EEF4" Offset="1"/> <GradientStop Color="#23AAF9" Offset="0.45"/> <GradientStop Color="#23AAF9" Offset="0.55"/> </LinearGradientBrush> </Setter.Value> </Setter> </Trigger> </Style.Triggers> </Style> </DataGrid.CellStyle> <DataGrid.Columns> <DataGridTextColumn Width="1.5*" Binding="{Binding Area}" Foreground="White" FontSize="50"/> <DataGridTextColumn Width="3.5*" Binding="{Binding AutoVin}" Foreground="White" FontSize="50"/> <DataGridTextColumn Width="2*" Binding="{Binding ErrCode}" Foreground="White" FontSize="50"/> </DataGrid.Columns> </DataGrid> </Grid>如何修改能够实现Area在一行,AutoVin在一行,ErrCode在一行
03-22
private ObservableCollection<DetectDetail> detailtable = new ObservableCollection<DetectDetail>(); public ObservableCollection<DetectDetail> DetailTable { get { return detailtable; } set { if (detailtable != value) { detailtable = value; RaisePropertyChanged(() => DetailTable); } } }public class DetectDetail : ViewModelBase { /// <summary> /// 区域 /// </summary> private string _Area = ""; public string Area { get { return _Area; } set { if (_Area != value) { _Area = value; RaisePropertyChanged(() => Area); } } } /// <summary> /// VIN /// </summary> private string _AutoVin = ""; public string AutoVin { get { return _AutoVin; } set { if (_AutoVin != value) { _AutoVin = value; RaisePropertyChanged(() => AutoVin); } } } /// <summary> /// 大数据错误码 /// </summary> private string _ErrCode = ""; public string ErrCode { get { return _ErrCode; } set { if (_ErrCode != value) { _ErrCode = value; RaisePropertyChanged(() => ErrCode); } } } } if (ModelRR.ResultDS.Tables[3].Rows.Count > 0) { var DetectDetailTable = ModelRR.ResultDS.Tables[3]; ObservableCollection<DetectDetail> table = new ObservableCollection<DetectDetail>(); for (int i = 0; i < DetectDetailTable.Rows.Count; i++) { DetectDetail rowData = new DetectDetail(); rowData.Area = DetectDetailTable.Rows[i]["Area"].ToString().Trim(); rowData.AutoVin = DetectDetailTable.Rows[i]["AutoVin"].ToString(); rowData.ErrCode = DetectDetailTable.Rows[i]["ErrCode"].ToString(); table.Add(rowData); } DetectData.DetailTable = table; }这是model和viemodel的相关代码,现在要求实现做一个三行的表格,表格第一行是Area的所有数据,第二行是VIN的所有数据,第三行是detail的所有数据
03-22
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白话Learning

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值