我试图在C# WPF MVVM中单击DataGrid中的按钮后添加另一行。问题是,只要我单击其他位置(例如在TextBox中),该行就会被添加。这意味着DataGrid在单击“添加行”按钮后不会立即更新。
NewDocumentView.xaml
<DataGrid x:Name="DataGrid"
AutoGenerateColumns="False"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Grid.Row="1"
Margin="20,350,0,0"
ItemsSource="{Binding Items}">
<DataGrid.Columns>
<DataGridTextColumn Header="Description" Binding="{Binding Description}" Width="500"/>
<DataGridTextColumn Header="Unit" Binding="{Binding Unit}" Width="100"/>
<DataGridTextColumn Header="Price" Binding="{Binding Price}" Width="100"/>
<DataGridTextColumn Header="Total" Binding="{Binding Total}" Width="100"/>
<DataGridTemplateColumn Header="Actions">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="Add Row" Command="{Binding AddItemCommand}" Width="100"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
字符串
NewDocumentViewModel.cs
namespace App.MVVM.ViewModel
{
internal class NewDocumentViewModel : ObservableObject
{
public ObservableCollection<Item> Items { get; set; } = new ObservableCollection<Item>();
public RelayCommand AddItemCommand { get; set; }
public NewDocumentViewModel()
{
Items = new ObservableCollection<Item>();
AddItemCommand = new RelayCommand(o => { AddNewItem(); });
}
private void AddNewItem()
{
Items.Add(new Item());
}
}
}
型
NewDocumentView.xaml.cs
namespace App.MVVM.View
{
public partial class NewDocumentView : UserControl
{
public NewDocumentView()
{
InitializeComponent();
DataContext = new NewDocumentViewModel();
}
}
}
型
Item.cs
namespace App.MVVM.Model
{
class Item : ObservableObject
{
private string _description;
public string Description
{
get { return _description; }
set
{
if (_description != value)
{
_description = value;
OnPropertyChanged(nameof(Description));
}
}
}
private string _unit;
public string Unit
{
get { return _unit; }
set
{
if (_unit != value)
{
_unit = value;
OnPropertyChanged(nameof(Unit));
}
}
}
private int _price;
public int Price
{
get { return _price; }
set
{
if (_price != value)
{
_price = value;
OnPropertyChanged(nameof(Price));
}
}
}
private int _total;
public int Total
{
get { return _total; }
set
{
if (_total != value)
{
_total = value;
OnPropertyChanged(nameof(Total));
}
}
}
}
}
型
ObservableObject.cs
namespace App.Core
{
internal class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
型
RelayCommand.cs
namespace App.Core
{
internal class RelayCommand : ICommand
{
private readonly Action<object> execute;
private readonly Func<object, bool> canExecute;
public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
this.execute = execute;
this.canExecute = canExecute;
}
public event EventHandler CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
public bool CanExecute(object parameter)
{
return canExecute == null || canExecute(parameter);
}
public void Execute(object parameter)
{
execute(parameter);
}
}
}
型
我做错了什么?我如何使用按钮立即更新DataGrid向DataGrid添加新行?
1条答案
按热度按时间2nbm6dog1#
当你将ObservableCollection绑定到datagrid的Itemssource时,集合中的每个Item都被模板化到一行中。每行的文本都是一个项。
绑定时,它会在Item ontext中查找属性。绑定到AddItemCommand会完全失败,因为Item没有AddItemCommand属性。
您可以使用相对搜索在可视树中搜索给定类型https://learn.microsoft.com/en-us/dotnet/desktop/wpf/advanced/relativesource-markupextension?view=netframeworkdesktop-4.8
如果你这样做是为了找到datagrid,那么它的datagontext是从NewDocumentView继承的,并且是NewDocumentViewModel。当然,这是你的命令所在的位置。
但是,您需要显式地告诉它使用DataContext上的属性,因为否则它将查看DatagridUI控件。
这里有一个简单的例子,我使用mvvm community toolkit来说明这一点,这个代码是快速的和肮脏的,只是为了说明这一点。
MainWindow
字符串
请注意,与相对对象绑定,我使用的是DataContext.AddItemCommand
视图模型:
型
当我单击该按钮时,将添加另一行。
如果你感兴趣,可能是一个想法,搜索和阅读适当的文章的工具包,但简短:
该工具包使用代码生成器在分部类中生成Items属性和AddItemCommand。