WPF:绑定到类内的列表 [英] WPF: bind to a List inside a class

查看:27
本文介绍了WPF:绑定到类内的列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 File 类定义如下

I have a File class defined as following

public class File
{
 public string FileName {set;get;}
 public List<Property> PropertyList;
}

Property 类如下所示:

Here is how Property class looks like:

public class Property
{
 public string PropertyName { set; get;};
 public string PropertyValue { set; get;};
 ...
}

我需要将 List 绑定到 DataGrid,显示 FileName.另外,我想为 PropertyList 中的每个 Property 创建一列,以PropertyName的字符串值作为列标题,PropertyValue的字符串值作为列的值.

I need to bind a List<File> to a DataGrid, display FileName. Also, I want to create a column for each Property in the PropertyList, with the string value of PropertyName as the column title, and string value of PropertyValue as the value of the column.

这在 WPF 中可行吗?

Is this possible in WPF?

谢谢,

推荐答案

刚刚尝试了这个奇怪但有趣的问题:-) 使用以下方法设法使其正常工作.对不起,答案很长,可能是详细的方法:-)

Just had to try this one, odd but funny problem:-) Managed to get it working by using the following. Sorry for the long answer, probably way to detailed :-)

首先,DataGrid.简单明了

First of, the DataGrid. Plain and simple

<DataGrid Name="c_dataGrid" AutoGenerateColumns="False"
          CanUserAddRows="False" CanUserDeleteRows="False"/>

然后是 File 类,名为 MyFile

Then the File class, named MyFile

public class MyFile
{
    public MyFile() : this(string.Empty) {}
    public MyFile(string fileName)
    {
        FileName = fileName;
        MyPropertyList = new ObservableCollection<MyProperty>();
    }

    public string FileName
    {
        set;
        get;
    }
    public ObservableCollection<MyProperty> MyPropertyList
    {
        get;
        set;
    }
}

属性类,名为 MyProperty

Property class, named MyProperty

public class MyProperty
{
    public MyProperty() : this(string.Empty, string.Empty) {}
    public MyProperty(string propertyName, string propertyValue)
    {
        MyPropertyName = propertyName;
        MyPropertyValue = propertyValue;
    }
    public string MyPropertyName
    {
        set;
        get;
    }
    public string MyPropertyValue
    {
        set;
        get;
    }
}

包含 MyFiles 的列表

A list containing MyFiles

public ObservableCollection<MyFile> MyFileList{ get; set; }

创建了一些虚拟数据来填充列表并在 DataGrid 上设置 ItemsSource

Created some dummy data to populate the list and set the ItemsSource on the DataGrid

MyFile myFile1 = new MyFile("MyFile1");
myFile1.MyPropertyList.Add(new MyProperty("Name1", "Value1"));
myFile1.MyPropertyList.Add(new MyProperty("Name2", "Value2"));
myFile1.MyPropertyList.Add(new MyProperty("Name3", "Value3"));
MyFile myFile2 = new MyFile("MyFile2");
myFile2.MyPropertyList.Add(new MyProperty("Name1", "Value1"));
myFile2.MyPropertyList.Add(new MyProperty("Name4", "Value4"));
myFile2.MyPropertyList.Add(new MyProperty("Name5", "Value5"));
MyFileList = new ObservableCollection<MyFile>();
MyFileList.Add(myFile1);
MyFileList.Add(myFile2);
c_dataGrid.ItemsSource = MyFileList;

为 FileName 属性添加了 DataGridTextColumn

Added a DataGridTextColumn for the FileName attribute

c_dataGrid.Columns.Add(GetNewMyFileNameColumn());

private DataGridColumn GetNewMyFileNameColumn()
{
    DataGridTextColumn myFileNameColumn = new DataGridTextColumn();
    myFileNameColumn.Header = "FileName";
    myFileNameColumn.Width = new DataGridLength(1.0, DataGridLengthUnitType.Auto);

    Binding valueBinding = new Binding();
    valueBinding.Path = new PropertyPath("FileName");
    valueBinding.Mode = BindingMode.TwoWay;
    valueBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
    valueBinding.NotifyOnSourceUpdated = true;
    valueBinding.NotifyOnTargetUpdated = true;

    myFileNameColumn.Binding = valueBinding;

    return myFileNameColumn;
}

然后是 MyPropertyList.我只想添加每个 MyPropertyName 一次,所以如果我有以下内容
我的文件1
-名称1
-名称2
-名称3
我的文件2
-名称1
-名称4
-名称5
生成的列应为 Name1、Name2、Name3、Name4 和 Name5.

And then for the MyPropertyList. I only wanted to add each MyPropertyName once so if I have the following
MyFile1
-Name1
-Name2
-Name3
MyFile2
-Name1
-Name4
-Name5
the generated columns shall be Name1, Name2, Name3, Name4 and Name5.

foreach (MyFile myFile in MyFileList)
{
    foreach (MyProperty myProperty in myFile.MyPropertyList)
    {
        if (ColumnAlreadyAdded(myProperty.MyPropertyName) == false)
        {
            c_dataGrid.Columns.Add(GetNewMyPropertyColumn(myProperty.MyPropertyName));
        }
    }
}

private bool ColumnAlreadyAdded(string myPropertyName)
{
    foreach (DataGridColumn dataGridColumn in c_dataGrid.Columns)
    {
        if (dataGridColumn.Header.ToString() == myPropertyName)
        {
            return true;
        }
    }
    return false;
}

private DataGridColumn GetNewMyPropertyColumn(string myPropertyName)
{
    DataGridTextColumn myFileNameColumn = new DataGridTextColumn();
    myFileNameColumn.Header = myPropertyName;
    myFileNameColumn.Width = new DataGridLength(1.0, DataGridLengthUnitType.Auto);

    Binding valueBinding = new Binding();
    valueBinding.Path = new PropertyPath("MyPropertyList");
    valueBinding.Converter = new MyPropertyConverter(myPropertyName);
    valueBinding.Mode = BindingMode.TwoWay;
    valueBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
    valueBinding.NotifyOnSourceUpdated = true;
    valueBinding.NotifyOnTargetUpdated = true;

    myFileNameColumn.Binding = valueBinding;

    return myFileNameColumn;
}

我必须将 MyPropertyName 提供给 Converter 的构造函数,以便它知道要查找哪个属性.
最后是转换器

I had to feed the MyPropertyName to the constructor of the Converter so it would know which property to look for.
And finally the Converter

public class MyPropertyConverter : IValueConverter
{
    private string m_propertyName = string.Empty;
    ObservableCollection<MyProperty> m_myPropertyList = null;

    public MyPropertyConverter(string propertyName)
    {
        m_propertyName = propertyName;
    }

    object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        m_myPropertyList = value as ObservableCollection<MyProperty>;
        if (m_myPropertyList == null)
        {
            return null;
        }
        foreach (MyProperty myProperty in m_myPropertyList)
        {
            if (myProperty.MyPropertyName == m_propertyName)
            {
                return myProperty.MyPropertyValue;
            }
        }
        return null;
    }

    object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (m_myPropertyList != null)
        {
            foreach (MyProperty myProperty in m_myPropertyList)
            {
                if (myProperty.MyPropertyName == m_propertyName)
                {
                    myProperty.MyPropertyValue = value.ToString();
                    break;
                }
            }
        }
        return m_myPropertyList;
    }
}

在 Convert 中,它将检查给定的 MyPropertyName,如果找到,则返回 MyPropertyValue,否则返回 null.ConvertBack 方法也是如此,但它会将 MyPropertyValue 设置为具有给定 MyPropertyName 的 MyProperty 的新值,然后返回列表或空列表.

In Convert it will check for the given MyPropertyName and if it finds it, return the MyPropertyValue, otherwise null. The same goes for the ConvertBack method but it will set MyPropertyValue to the new value for the MyProperty with the given MyPropertyName and then return the list which is either a list or null.

不在 MyFile 列表中的属性将不可编辑,它们只会在离开单元格时变回 null(这可能是重点).

The properties that aren't in a MyFile list won't be editable, they will just change back to null upon leaving the cell (which is probably the point).

这将导致 DataGrid 看起来像这样.

This will result in a DataGrid that looks like this.

这篇关于WPF:绑定到类内的列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆