WPF - DataGrid со столбцами для различных объектов, которые получены из абстрактного класса - PullRequest
0 голосов
/ 11 ноября 2019

Я сделал минималистичный пример своей проблемы. Сначала здесь диаграмма классов Диаграмма классов

Что я хочу: я хочу отобразить каждое свойство из класса A в сетке данных WPF с возможностью редактирования каждого свойства.

Если я просто добавлю объект A в ObservableCollection и добавлю его в качестве ItemsSource в DataGrid, результат, как и ожидалось, не тот, который мне нужен.

Вот почему я добавил следующий класс:

public class DataGridRowObjects
{
    public A ObjectA { get; set; }
    public B ObjectB { get; set; }
    public AbstractC ObjectC { get; set; }
}

Проблема в том, что некоторые ячейки будут пустыми из-за AbstractC . Если у меня ConcreteC1 , я хочу, чтобы столбцы, заданные ConcreteC1 , были доступны для редактирования. Если в этой строке есть объект ConcreteC2 , я хочу отключить эти ячейки с помощью некоторого текста, например свойство недоступно .

Я получил решение этой проблемы,но моя проблема в качестве кода (очень некрасивое решение) с мыслью о поддержке.

Это мой подход к решению проблемы, чтобы иметь возможность редактировать каждое свойство в этой сетке данных Результат в действии :

<DataGrid x:Name="dataGridForA" AutoGenerateColumns="False" CanUserAddRows="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="PropertyAA" Binding="{Binding ObjectA.PropertyAA}"/>
            <DataGridTextColumn Header="PropertyAB" Binding="{Binding ObjectA.PropertyAB}"/>
            <DataGridTextColumn Header="PropertyBA" Binding="{Binding ObjectB.PropertyBA}"/>
            <DataGridTextColumn Header="PropertyAbstractCA" Binding="{Binding ObjectC.PropertyAbstractCA}" />
            <DataGridTemplateColumn Header="PropertyConcreteC1A">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ContentPresenter Content="{Binding ObjectC}">
                            <ContentPresenter.Resources>
                                <DataTemplate DataType="{x:Type model:ConcreteC1}">
                                    <TextBlock Text="{Binding PropertyConcreteC1A}" />
                                </DataTemplate>
                                <DataTemplate DataType="{x:Type model:ConcreteC2}">
                                    <TextBlock Text="Property not available" />
                                </DataTemplate>
                            </ContentPresenter.Resources>
                        </ContentPresenter>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <!-- Some cool stuff to edit properties -->
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn Header="PropertyConcreteC2A">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ContentPresenter Content="{Binding ObjectC}">
                            <ContentPresenter.Resources>
                                <DataTemplate DataType="{x:Type model:ConcreteC2}">
                                    <TextBlock Text="{Binding PropertyConcreteC2A}" />
                                </DataTemplate>
                                <DataTemplate DataType="{x:Type model:ConcreteC1}">
                                    <TextBlock Text="Property not available" />
                                </DataTemplate>
                            </ContentPresenter.Resources>
                        </ContentPresenter>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <!-- Some cool stuff to edit properties -->
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>

Проблема в части с DataGridTemplateColumn . В этом примере это выглядит довольно просто. Но в моей реальной задаче у меня есть еще много свойств и в настоящее время четыре класса, которые происходят от AbstractC . Который в конечном итоге будет выглядеть как четыре DataTemplates для каждого ConcreteC-Class и для каждого свойства этих ConcreteC-Classes . XAML в моей реальной проблеме взорвется и не подлежит ремонту. Может быть, у некоторых из вас есть другое решение?

Приложение

Вот классы, может быть, для лучшего обзора и как я настраиваю Datagrid ItemsSource

public class A
{
    public string PropertyAA { get; set; }
    public string PropertyAB { get; set; }

    public List<B> ListB { get; set; }
}

public class B
{
    public string PropertyBA { get; set; }
    public List<AbstractC> ListAbstractC { get; set; }
}

public abstract class AbstractC
{
    public string PropertyAbstractCA { get; set; }
}

public class ConcreteC1 : AbstractC
{
    public string PropertyConcreteC1A { get; set; }
}

public class ConcreteC2 : AbstractC
{
    public string PropertyConcreteC2A { get; set; }
}

Настройка:

public class DataGridRowObjects
{
    public A ObjectA { get; set; }
    public B ObjectB { get; set; }
    public AbstractC ObjectC { get; set; }
}
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public List<A> aList = new List<A>();

    public ObservableCollection<DataGridRowObjects> modelList = new ObservableCollection<DataGridRowObjects>();

    public MainWindow()
    {
        InitializeComponent();
        ConcreteC1 concreteC1A = new ConcreteC1 { PropertyAbstractCA = "TestA1", PropertyConcreteC1A = "TestConcrete1A" };
        ConcreteC2 concreteC2A = new ConcreteC2 { PropertyAbstractCA = "TestA2", PropertyConcreteC2A = "TestConcrete2A" };

        ConcreteC1 concreteC1B = new ConcreteC1 { PropertyAbstractCA = "TestB1", PropertyConcreteC1A = "TestConcrete1B" };
        ConcreteC2 concreteC2B = new ConcreteC2 { PropertyAbstractCA = "TestB2", PropertyConcreteC2A = "TestConcrete2B" };

        List<AbstractC> concreteAs = new List<AbstractC>();
        concreteAs.Add(concreteC1A);
        concreteAs.Add(concreteC2A);

        B bA = new B { ListAbstractC = concreteAs, PropertyBA = "bA" };

        List<AbstractC> concreteBs = new List<AbstractC>();
        concreteBs.Add(concreteC1B);
        concreteBs.Add(concreteC2B);

        B bB = new B { ListAbstractC = concreteBs, PropertyBA = "bB" };

        List<B> bList = new List<B>();
        bList.Add(bA);
        bList.Add(bB);

        A objectA = new A {PropertyAA = "AA", PropertyAB = "AB", ListB = bList};
        aList.Add(objectA);


        foreach (A a in aList)
        {
            foreach (B b in a.ListB)
            {
                foreach (AbstractC c in b.ListAbstractC)
                {
                    this.modelList.Add(new DataGridRowObjects { ObjectA = a, ObjectB = b, ObjectC = c });
                }
            }
        }
        this.dataGridForA.ItemsSource = modelList;
    }
}

1 Ответ

0 голосов
/ 11 ноября 2019

Кажется, вам не хватает свойства Fallbackvalue привязки.

<DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
        <TextBlock Text="{Binding PropertyConcreteC2A, FallbackValue='Property Not Available' }" />
     </DataTemplate>
</DataGridTemplateColumn.CellTemplate>

Это поможет, и, возможно, вы сможете еще больше упростить его. Пожалуйста, проверьте следующие ссылки также для получения дополнительной информации:

c-sharpcorner

документы Microsoft

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