繁体   English   中英

WPF:数据绑定到DataGrid

[英]WPF: Databinding to a DataGrid

这是我在这个论坛上的第一篇文章,尽管我是一个长期的潜伏者。 我已经开始学习WPF大约两个月了,我正在尝试创建一个仅用于培训目的的应用程序。

我有一个后端数据库,该数据库已使用EF6 ORM添加到我的应用程序中。 在我的应用程序中,我有一个`ComboBox,需要由数据库表中的一列填充。 我可以使用绑定到列表来完成。

我遇到麻烦的部分是DataGrid 需要根据ComboBox选择的Item填充DataGrid的列。

我的数据库:

这是我的数据库结构

如您所见,学校有几个系,每个系都有一个HOD和一个学生实力。

我的应用程序:

这是应用程序的快照

ComboBox将填充学校名称。 选择学校名称后,将填充DataGrid DataGrid将为学校的每个部门提供每一行。 因此,我需要将相应的列与相应学校的部门绑定。 我得到了。 但是,然后我想将用户输入的注释保存在Feedback TextBox

我不明白如何创建一个类,以便可以将DataGrid绑定到它的对象。 是否可以将DataGrid绑定到对象,然后将列分别绑定到另一个对象?

编辑

除了从数据库创建的实体之外,我还有两个类:

class Feedback : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private string _school;

    public string School
    {
        get
        {
            return _school;
        }

        set
        {
            _school = value;
            OnPropertyChanged("School");
        }
    }

    private ObservableCollection<FeedbackLine> _feedbackLines;

    public ObservableCollection<FeedbackLine> FeedbackLines
    {
        get
        {
            return _feedbackLines;
        }

        set
        {
            _feedbackLines = value;
            OnPropertyChanged("FeedbackLines");
        }
    }

    public Feedback(string school)
    {
       //Insert some Linq Query to populate the FeedbackLines
       //something like
       //var FeedbackLines = Context.Schools.Where(c => c.SchoolName == school)
       //                                   .Select(c => new {Department = c.AvailableDepts.Dept, etc etc}.ToList();
       //but then what?
    }

    private void OnPropertyChanged(string v)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(v));
    }
}

这应该绑定到数据网格。 而FeedbackLine是:

public class FeedbackLine: INotifyPropertyChanged
{
    private string _dept;

    public string Department
    {
        get { return _dept; }
        set { _dept = value;
            OnPropertyChanged("Department");
        }
    }

    private string _HOD;

    public string HOD
    {
        get { return _HOD; }
        set { _HOD = value;
            OnPropertyChanged("HOD");
        }
    }

    private int _strength;

    public int Strength
    {
        get { return _strength; }
        set { _strength = value;
            OnPropertyChanged("Strength");
        }
    }

    private bool _isSelected;

    public bool Selected
    {
        get { return _isSelected; }
        set { _isSelected = value;
            OnPropertyChanged("Selected");
        }
    }

    private string _comment;

    public string Comment
    {
        get { return _comment; }
        set { _comment = value;
            OnPropertyChanged("Comment");
        }
    }

    private void OnPropertyChanged(string v)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(v));
    }



    public event PropertyChangedEventHandler PropertyChanged;
}

我在ViewModel上没有什么进展。 问题是,我对LINQ不太满意。 而且有太多的类和对象,我不知道该绑定哪个类和对象。 我能得到的唯一模糊的想法是,我必须使用LINQ来使用选定的School来查询数据库,然后使用该表来填充FeedbackLines

编辑2:对于感兴趣的任何人,这是我在WPF中的模型图模型图

编辑3:我认为我对ViewModel感到困惑。 屏幕上显示的数据不一定是要保存的数据。 例如,我不想保存未选择的行。 我的Feedback类尝试显示并保存数据。 问题就在这里。 不能将DataGrid绑定到对象,而将其列绑定到其他对象? 例如,如果我选择对部门使用组合Combobox 然后,我需要使用ItemsSource来显示项目,但只需要保存SelectedItem 我找不到将这两个问题分开的方法。

我会更改您的Feedback构造函数

public Feedback(string school, List<FeedbackLine> feedbackLines)
{
    School = school;
    FeedbackLines = new ObservableColleytion<FeedbackLine>(feedbackLines);
}

如果您的数据视图模型没有与数据库的连接,则它是一种更好的体系结构。 您可以将选择放在单独的类中。

如果您需要有关LINQ语句的帮助,我可以为您提供帮助。

在您的Feedback构造函数中,您编写了

//but then what?

收到数据后,您可以创建FeedbackLines实例,以将它们添加到上面显示的新构造函数中。

完成此操作后,您的viewmodel(即视图的DataContext)需要一个

public void ObservableCollection<Feedback> Feedbacks

使用INotifyPropertyChanged就像在其他视图模型中一样。

在您的xaml中,您可以在学校中找到ComboBox。 给该组合框起一个名字,例如SchoolsComboBox。 在您的DataGrid中编写以下行

Source={Binding ElementName=SchoolsComboBox, Path=SelectedItem.FeedbackLines}

/ edit用于添加LINQ您创建了一个匿名类型。 只需创建一个FeedbackLine,就可以了。

var feedbackLines = Context.Schools.Where(c => c.SchoolName == school)
                                    .Select(c => new FeedbackLine
                                            {
                                                Department = c.AvailableDepts.Dept, 
                                                HOD = c.AvailableDepts.HeadOfDept, 
                                                Strength = c.AvailableDepts.StudentStrength}
                                    .ToList()

你可以做这样的事情。 我敢肯定它可以写得更好,但它可以工作。

在您的ViewModel中,制作3个实现INotifyPropertyChanged的属性

一个用于您的集合,它将绑定到您的ComboBox(将其设置为ObservableCollection),一个用于您的ComboBox的SelectedItem(将其绑定到comboBox中的SelectedItem),另一个用于将ObservableCollection绑定到DataGrid)

例如,您在XAML中:

<Grid>
        <ComboBox ItemsSource="{Binding Products}"
                  SelectedItem="{Binding SelectedProduct}"
                  HorizontalAlignment="Left"
                  VerticalAlignment="Top"
                  Width="200"
              Margin="20"
              IsSynchronizedWithCurrentItem="True" />

    <DataGrid ItemsSource="{Binding SelectedOne}"
              HorizontalAlignment="Right "
              VerticalAlignment="Center"
              Width="300"
              IsSynchronizedWithCurrentItem="True">
    </DataGrid>

在您的ViewModel中,您可以拥有类似的内容。

     public ObservableCollection<Product> Products
            {
                get { return _products; }
                set
                {
                    if (value != _products)
                    {
                        _products = value;
                        OnPropertyChanged();
                    }
                }
            }

            private ObservableCollection<Product> _selectedOne;
            public ObservableCollection<Product> SelectedOne
            {
                get { return _selectedOne; }
                set { 
                       _selectedOne = value; 
                       OnPropertyChanged();
                     }
            }

            public int SelectedProductId
            {
                get { return _selectedProductId; }
                set
                {
                    if (value != _selectedProductId)
                    {
                        _selectedProductId = value;
                        OnPropertyChanged();
                    }
                }
            }

            public Product SelectedProduct
            {
                get { return _selectedProduct; }
                set
                {
                    if (value ! = _selectedProduct) 

                {
                    _selectedProduct = value;

                    // clear your list of selected objects and then add just selected one
                    // or you dont clear it, and items will be added in DataGrid when selected in ComboBox
                    SelectedOne.Clear();
                    SelectedOne.Add(_selectedProduct);

                    OnPropertyChanged();
                }
            }
        }


        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged = delegate { };

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion

通过代码填充产品,可以通过从ComboBox中选择Item来填充DataGrid。

您可以进入ViewModel构造函数并进行类似的操作。

public MainWindowViewModel()
        {
            if (!DesignerProperties.GetIsInDesignMode(new DependencyObject()))
            {
                using (YourDbContext context = new YourDbContext ())
                {
                    var productList = new ObservableCollection<Product>(context.Products);
                    productList.ToList()
                    Products = productsList;
                }
            }
        }

暂无
暂无

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

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