WPF:数据绑定到DataGrid

时间:2017-03-10 01:09:17

标签: c# wpf data-binding datagrid

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

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

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

我的数据库:

Here is my database structure

正如你所看到的,学校有几个部门,每个部门都有一个HOD和学生的力量。

我的申请:

Here is the snapshot of the app

ComboBox将填充学校名称。选择学校名称后,将填充DataGridDataGrid将为学校提供每个部门的每一行。所以我需要将相应的列绑定到相应学校的部门。我得到了很多。但是,我想在反馈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));
    }
}

这应该绑定到datagrid。而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中的模型图: Model Diagram

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

2 个答案:

答案 0 :(得分:0)

我会更改您的反馈构造函数

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

如果您的数据视图模型没有与数据库的连接,那么这是一个更好的架构。你可以将你的选择放在一个单独的类中。

如果您需要LINQ声明的帮助,我可以帮助您。

在您编写的反馈构造函数中

//but then what?

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

当你这样做时,你的viewmodel(你的视图的DataContext)需要一个

public void ObservableCollection<Feedback> Feedbacks

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

在你的xaml中你有你的ComboBox和学校。给这个组合框命名,例如SchoolsComboBox。 在你的DataGrid中写下这一行

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

/编辑添加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()

答案 1 :(得分:0)

你可以做像这样的东西。我确定它可以写得更好但是有效。

在ViewModel中创建实现INotifyPropertyChanged的3个属性

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

例如,你有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;
                }
            }
        }