WPF: привязка к списку внутри класса - PullRequest
3 голосов
/ 19 октября 2010

У меня есть класс File, определенный следующим образом

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

Вот как выглядит класс Property:

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

Мне нужно связать List<File> с DataGrid, отобразитьИмя файла.Кроме того, я хочу создать столбец для каждого Property в PropertyList со строковым значением PropertyName в качестве заголовка столбца и строковым значением PropertyValue в качестве значения столбца.

Возможно ли это в WPF?

Спасибо,

1 Ответ

1 голос
/ 20 октября 2010

Просто нужно было попробовать эту странную, но забавную проблему :-) Удалось заставить ее работать, используя следующее.Извините за длинный ответ, вероятно, способ подробно :-)

Прежде всего, DataGrid.Простой и простой

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

Затем класс File с именем 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

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

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

Созданы некоторые фиктивные данные для заполнения списка и установки ItemsSource в 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;

Добавлен DataGridTextColumn для атрибута FileName

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 только один раз, поэтому, если у меня есть следующее
MyFile1
-Name1
-Name2
-Name3
MyFile2
-Name1
-Name4
-Name5
сгенерированные столбцы должны быть Name1, Name2, Name3, Name4 и 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 в конструктор конвертера, чтобы он знал, какое свойство искать.
И, наконец, конвертер

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;
    }
}

In Преобразовать егопроверит указанное имя MyPropertyName и, если оно его найдет, вернет MyPropertyValue, в противном случае - ноль.То же самое относится и к методу ConvertBack, но он установит для MyPropertyValue новое значение для MyProperty с заданным MyPropertyName, а затем вернет список, являющийся либо списком, либо нулевым.

Свойства, которых нет вСписок MyFile не будет редактироваться, он просто изменится на ноль при выходе из ячейки (что, вероятно, является точкой).

Это приведет к созданию DataGrid, который выглядит следующим образом.

alt text

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...