简体   繁体   English

如何将DataGrid绑定到WPF和MVVM中的动态可变数据和用户输入

[英]How to Bind DataGrid to dynamically changeable data and User Inputs in WPF and MVVM

I´m quite new to WPF and I want to show in my UserControl something like this: Sample Image 我是WPF的新手,我想在UserControl中显示如下内容: 示例图像

I get data from different sources: 我从不同来源获取数据:

Columns: 列:

ID: always present ID:始终存在

Problem 1 ...n: I have an XML-file like this one 问题1 ... n:我有一个像这样的XML文件

from which I want to get the Columns for the Problems. 我想从中获取问题专栏。 There can be a variable number of Problems. 问题的数量可以变化。

Grade: always present 年级:始终存在

Rows: 行:

Each Row should only contain Textboxes (some are read-only for the user). 每行仅应包含文本框(某些对用户而言是只读的)。

The Data in the ID Column comes from a file. ID列中的数据来自文件。

The Values for the Problems are input by the user. 问题的值由用户输入。

The Data under Grade will be calculated. 将计算成绩下的数据。

The input values for the Problems and the calculated value for Grade are related to the ID. 问题的输入值和成绩的计算值与ID相关。

I tried to implement this by using a DataGrid and setting up DataGridTemplateColumn for the Problem Columns but was not really successful. 我尝试通过使用DataGrid并为问题列设置DataGridTemplateColumn来实现此目的,但并没有真正成功。 I think this would be the right control in this case, but I can´t really figure out how to set this up. 我认为在这种情况下这将是正确的控制,但是我真的无法弄清楚如何进行设置。

I thought about building this "Table" manually, by adding Labels and Textboxes for the "Problems" depending on the Data. 我考虑过通过根据数据为“问题”添加标签和文本框来手动构建此“表”。 But then my ViewModel should know something about the View which violates MVVM. 但是,然后我的ViewModel应该了解有关违反MVVM的View的一些知识。

Thanks and best regards. 谢谢和最好的问候。

EDIT: Thanks, @Ivan Furdek for your help so far! 编辑:谢谢@Ivan Furdek到目前为止的帮助! I got to show now each textbox and column for the Problems and can edit them. 现在,我必须显示问题的每个文本框和列,并可以对其进行编辑。 But my Collection won´t be updated -.- so my List<double> PointsPerProblems stays on the intialized values 但是我的收藏集不会更新-.-所以我的List<double> PointsPerProblems保持初始化值

Here is my XAML: 这是我的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>

My Model: 我的模特:

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

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

    public double Grade { get; set; }

    public double TotalScore { get; set; }
}

And the specific parts of my ViewModel: 还有我的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 found the Solution for the last problem here in 2nd edit of the answer 确定在答案的第二次编辑中找到了最后一个问题的解决方案

WPF: How to make DataGrid binding with dynamic columns editable? WPF:如何使带有动态列的DataGrid绑定可编辑?

You'll need to parse the xml into a list of objects like 您需要将xml解析为一系列对象,例如

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

After that I suggest you follow this method to get the required display: https://blogs.msmvps.com/deborahk/populating-a-datagrid-with-dynamic-columns-in-a-silverlight-application-using-mvvm/ 之后,我建议您按照以下方法获取所需的显示: https : //blogs.msmvps.com/deborahk/populating-a-datagrid-with-dynamic-columns-in-a-silverlight-application-using-mvvm/

Make sure to use two way binding, and UpdateSourceTrigger = PropertyChanged so the changes get propagated back to the list. 确保使用双向绑定,并且使用UpdateSourceTrigger = PropertyChanged以便将更改传播回列表。

The columns for id and score should be have their IsReadOnly property set to true. id和score列应将其IsReadOnly属性设置为true。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM