不显示WPF DataGrid DataBinding
我在我当前的WPF应用程序中有一个DataGrid,我想绑定到包含ObservableCollection的ViewModel。 用户可以在某些文本框中输入搜索值,并且在输入完成后,我正在对我们的数据库执行查询,以重新查询记录表。 从这些记录中填充ObservableCollection的数据。 现在我正在构造数据网格不显示数据。
我已经阅读了一堆关于绑定的帖子,但我仍然错过了一些我认为的东西。
Product.cs
public class Product : InotifyPropertyChanged, IEditableObject
{
public string Title { get; set; } = "";
//public Product()
//{
//}
private ProductViewModel _productViewModel = new ProductViewModel();
public ProductViewModel productViewModel { get { return _productViewModel; } set { _productViewModel = value; } }
public DataTable ProductsTable { get; set; }
public void GetProducts(string filter)
{
//< --doing some stuff to fill the table-->
foreach (DataRow row in ProductsTable.Rows)
{
productViewModel.Products.Add(new Product
{
Title = (string)row["TITLE"],
});
}
}
}
ProductViewModel.cs
public class ProductViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private Product _SelectedProduct;
private ObservableCollection<Product> _Products = new ObservableCollection<Product>();
public ObservableCollection<Product> Products { get { return _Products; } set { _Products = value; } }
public ProductViewModel()
{
}
public void NotifyPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
ProductWindow.xaml
<DataGrid
Name="ProductsGrid"
AutoGenerateColumns="False"
ItemsSource="{Binding Products, Mode=TwoWay, NotifyOnSourceUpdated=True}"
SelectedItem="{Binding SelectedProduct, Mode=TwoWay}"
CanUserAddRows="False" SelectionUnit="FullRow"
VerticalAlignment="Stretch"
Grid.Row="0"
Margin="10,10,10,10"
>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Title}" Header="Title"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
ProductWindow.xaml.cs
public partial class ProductWindow : Page
{
public object DialogResult { get; private set; }
//public ProductViewModel ProductViewModel;
public ProductWindow()
{
InitializeComponent();
DataContext = new ProductViewModel();//stackflow
//var ProductViewModel = products.ProductViewModel;
//ProductsGrid.DataContext = new ProductViewModel();
}
public ProductViewModel ViewModel => DataContext as ProductViewModel;
private void OnKeydownHandler(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
var tb = sender as TextBox;
Product products = new Product();
string filter = "";//performing some ifelse to create filter
products.GetProducts(filter);
//ProductsGrid.DataContext = products.ProductsTable;
//ProductsGrid.DataContext = products.productViewModel;
}
else if (e.Key == Key.Escape)
{
ProductsGrid.DataContext = null;
foreach (TextBox tb in FindVisualChildren<TextBox>(this))
{
// do something with tb here
tb.Text = "";
}
}
}
}
如果DataContext
是ProductViewModel
,而Products
是集合ProductViewModel
填充,你会看到在你行DataGrid
。 我测试过了。 看来你给它的视图模型可能没有任何行。
也就是说,你的设计有一个问题:
Product
创建一个ProductViewModel
。 ProductViewModel
创建一个Product
的集合。 正如我刚才所说的,每个Product
都会创建一个ProductViewModel
。 这创建了一个Product
集合。 他们不断创建对方,直到出现StackOverflowException
。 如果你没有看到,你必须从其他地方调用GetProducts()。
但是Product
不需要拥有ProductViewModel
的副本。 这就像为汽车上的每个车轮添加一辆汽车。
所以让我们来做这个: ProductViewModel
拥有一个Product
的集合。 只是。 我们将调用GetProducts()
来确保我们在网格中获得一些项目。 你的绑定很好。 你只是没有填充集合。
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ProductViewModel();
}
// Now you can call ViewModel.GetProducts(filterString) from an event handler.
// It would be more "correct" to use a Command, but let's take one step at a time.
public ProductViewModel ViewModel => DataContext as ProductViewModel;
}
的ViewModels
// You didn't include any implementation of IEditableObject. I presume
// you can add that back in to this version of the class.
public class Product : INotifyPropertyChanged, IEditableObject
{
// You weren't raising PropertyChanged here, or anywhere at all.
// In every setter on a viewmodel, you need to do that.
private string _title = "";
public string Title {
get => _title;
set
{
if (_title != value)
{
_title = value;
NotifyPropertyChanged(nameof(Title));
}
}
}
public Product()
{
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class ProductViewModel : INotifyPropertyChanged
{
public ProductViewModel()
{
GetProducts("");
}
public event PropertyChangedEventHandler PropertyChanged;
private Product _SelectedProduct;
public Product SelectedProduct
{
get { return _SelectedProduct; }
set
{
if (value != _SelectedProduct)
{
_SelectedProduct = value;
NotifyPropertyChanged(nameof(SelectedProduct));
}
}
}
public DataTable ProductsTable { get; set; }
public void GetProducts(string filter)
{
//< --doing some stuff to fill the table-->
Products.Clear();
foreach (DataRow row in ProductsTable.Rows)
{
Products.Add(new Product
{
Title = (string)row["TITLE"],
});
}
}
private ObservableCollection<Product> _Products = new ObservableCollection<Product>();
// This setter MUST raise PropertyChanged. See the Title property above for example.
public ObservableCollection<Product> Products { get { return _Products; } private set { _Products = value; } }
public void NotifyPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
更新
问题在于:您创建了一个新的Product
,该Product
创建了自己的ProductsViewModel
。 没有任何东西绑定到该视图模型的任何属性。 您填充它的集合并且DataGrid不知道或关心,因为您将其ItemsSource绑定到不同对象的属性。
所以使用我的建议,特别是窗口的ViewModel
属性。 我只是对您需要复制的ProductsViewModel.GetProducts()进行更改 :现在它在填充集合之前调用Products.Clear()
。
if (e.Key == Key.Enter)
{
var tb = sender as TextBox;
// Don't create this
//Product products = new Product();
string filter = "";//performing some ifelse to create filter
ViewModel.GetProducts(filter);
}
else if (e.Key == Key.Escape)
{
// Setting the DataContext to null breaks everything. Never do that.
//ProductsGrid.DataContext = null;
// Instead, just clear the collection. It's an ObservableCollection so it will
// notify the DataGrid that it was cleared.
ViewModel.Products.Clear();
foreach (TextBox tb in FindVisualChildren<TextBox>(this))
{
// do something with tb here
tb.Text = "";
}
}
链接地址: http://www.djcxy.com/p/75243.html