这是我在这个论坛上的第一篇文章,虽然我是一个长期的潜伏者。我已经开始学习WPF大约几个月了,我正在尝试创建一个仅用于培训目的的应用程序。
我有一个后端数据库,我已使用EF6 ORM添加到我的应用程序中。在我的应用程序中,我有一个`ComboBox,需要由数据库表中的列填充。我可以使用绑定到列表来做。
我遇到问题的部分是DataGrid
。需要根据DataGrid
中选择的Item
填充ComboBox
的列。
我的数据库:
正如你所看到的,学校有几个部门,每个部门都有一个HOD和学生的力量。
我的申请:
ComboBox
将填充学校名称。选择学校名称后,将填充DataGrid
。 DataGrid
将为学校提供每个部门的每一行。所以我需要将相应的列绑定到相应学校的部门。我得到了很多。但是,我想在反馈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
。我无法找到将这两个问题分开的方法。
答案 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;
}
}
}