Как привязать DataGrid к динамически изменяемым данным и пользовательским входам в WPF и MVVM - PullRequest
0 голосов
/ 26 февраля 2019

Я довольно новичок в WPF и хочу показать в своем UserControl что-то вроде этого: Образец изображения

Я получаю данные из разных источников:

Столбцы:

ID: всегда присутствует

Проблема 1 ... n: У меня есть XML-файл, такой как этот

из которого я хочу получить столбцы для задач.Количество проблем может варьироваться.

Оценка: всегда присутствует

Строки:

Каждая строка должна содержать только текстовые поля (некоторые из них предназначены для чтения.только для пользователя).

Данные в столбце идентификатора получены из файла.

Значения для проблем вводятся пользователем.

Данные в классебудет вычислено.

Входные значения для Проблем и вычисленное значение для Оценки связаны с идентификатором.

Я попытался реализовать это с помощью DataGrid инастройка DataGridTemplateColumn для столбцов Problem , но на самом деле не удалось.Я думаю, что в данном случае это будет правильный контроль, но я не могу понять, как это настроить.

Я думал о создании этой «таблицы» вручную, добавив метки и текстовые поля для «Проблемы »в зависимости от данных.Но тогда моя ViewModel должна знать что-то о представлении, которое нарушает MVVM.

Спасибо и наилучшие пожелания.

РЕДАКТИРОВАТЬ: Спасибо, @Ivan Furdek за вашу помощь!Теперь я должен показать каждое текстовое поле и столбец для Проблем и редактировать их.Но моя Коллекция не будет обновлена ​​- поэтому мой List<double> PointsPerProblems остается на инициализированных значениях

Вот мой XAML:

<ItemsControl ItemsSource="{Binding PointsPerProblems, Mode=TwoWay, 
             UpdateSourceTrigger=PropertyChanged}">                                            
         <ItemsControl.ItemsPanel>
             <ItemsPanelTemplate>
                 <StackPanel Orientation="Horizontal"/>
             </ItemsPanelTemplate>
         </ItemsControl.ItemsPanel>
         <ItemsControl.ItemTemplate>
             <DataTemplate>
                 <Border Width="70">
                     <TextBox Text="{Binding Path=., Mode=TwoWay,
                      UpdateSourceTrigger=PropertyChanged}"
                      TextAlignment="Center"/>
                 </Border>
             </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Моя модель:

public class GradingModel
{
    public string MatriculationNumber { get; set; }

    public List<double> PointsPerProblems { get; set; }

    public double Grade { get; set; }

    public double TotalScore { get; set; }
}

И конкретные части моей ViewModel:

public ObservableCollection<GradingModel> Gradings
    {
        get
        {
            return this.gradings;
        }

        set
        {
            this.gradings = value;
            this.OnPropertyChanged(nameof(this.Gradings));
        }
    }

public List<string> ProblemList
    {
        get
        {
            return this.problemList;
        }

        set
        {
            this.problemList = value;
            this.OnPropertyChanged(nameof(this.ProblemList));
        }
    }
private void GetGradingForm()
    {
        ExamRatingDTO examRatingModel = new ExamRatingDTO();
        List<StudentDTO> students = new List<StudentDTO>();

        this.messageBoxService.ShowInfoMessage(
            "Please Select a xml-File containing the Exam Ratings.",
            "Select a Exam Rating File.");
        try
        {
           examRatingModel = this.fileDialogService.OpenLoadFileDialog<ExamRatingDTO>();
        }
        catch (InvalidOperationException ex)
        {
            this.messageBoxService.ShowErrorMessage("Please select a correct Exam Rating File.", ex);
        }

        this.messageBoxService.ShowInfoMessage(
            "Please Select a xml-File containing the Students Information.",
            "Select a Student Information File.");
        try
        {
            students = this.fileDialogService.OpenLoadFileDialog<List<StudentDTO>>();
        }
        catch (InvalidOperationException ex)
        {
            this.messageBoxService.ShowErrorMessage("Please select a correct Students File.", ex);
        }

        foreach (var student in students)
        {
            this.Gradings.Add(new GradingModel()
            {
                MatriculationNumber = student.MatriculationNumber.ToString(),
                PointsPerProblems = new List<double>(),
                Grade = 0.0,
                TotalScore = 0.0
            });
        }

        List<string> tmpProblemList = new List<string>();

        foreach (var problem in examRatingModel.PointsPerProblems)
        {
            tmpProblemList.Add(problem.ProblemName);
        }

        foreach (var grading in this.Gradings)
        {
            for (int i = 0; i < tmpProblemList.Count; i++)
            {
                grading.PointsPerProblems.Add(0.0);
            }
        }

        this.ProblemList = tmpProblemList;
    }

EDIT

Ok нашел решение для последней проблемы здесь во 2-м редактировании ответа

WPF: как сделать привязку DataGrid к динамическим столбцам редактируемым?

1 Ответ

0 голосов
/ 27 февраля 2019

Вам нужно будет разобрать xml в список объектов, таких как

    public class Student 
    { 
        public int Id { get; set; } 
        public List<decimal> ProblemScores { get; set; } 
        public DecimalGrade
        { 
            get
            {
               return ProblemScores.Average();
            }
        } 

После этого я предлагаю вам воспользоваться этим методом, чтобы получить требуемый экран: https://blogs.msmvps.com/deborahk/populating-a-datagrid-with-dynamic-columns-in-a-silverlight-application-using-mvvm/

Makeобязательно используйте двустороннюю привязку и UpdateSourceTrigger = PropertyChanged, чтобы изменения распространялись обратно в список.

Для столбцов id и Score их свойство IsReadOnly должно иметь значение true.

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