WPF 绑定到可观察集合 - 仅在行完成时更新集合
本文关键字:集合 完成时 更新 观察 WPF 绑定 | 更新日期: 2023-09-27 18:30:16
我有一个基本DataGrid
,我用它来为我一直在玩的游戏项目创建敌人列表:
<DataGrid x:Name="EnemyGrid" Margin="0,10,0,0" VerticalAlignment="Top" RenderTransformOrigin="8.273,3.781" Height="162" ItemsSource="{Binding}" CanUserReorderColumns="False" ColumnWidth="*" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name, UpdateSourceTrigger=Explicit}" ClipboardContentBinding="{x:Null}" Header="Name"/>
<DataGridTextColumn Binding="{Binding Level, UpdateSourceTrigger=Explicit}" ClipboardContentBinding="{x:Null}" Header="Level"/>
<DataGridTextColumn Binding="{Binding Role, UpdateSourceTrigger=Explicit}" ClipboardContentBinding="{x:Null}" Header="Role"/>
</DataGrid.Columns>
</DataGrid>
DataGrid
绑定到从json
文件中读入的ObservableCollection
:
public partial class MainWindow : Window
{
public ObservableCollection<Enemy> EnemyList;
public MainWindow()
{
InitializeComponent();
var data = JsonHelpers.ReadFile<Enemy>("Enemy.json");
EnemyList = data["Enemy"];
EnemyGrid.DataContext = EnemyList;
}
}
如果重要,ReadFile 方法使用 JSON.Net
public static Dictionary<string, ObservableCollection<T>> ReadFile<T>(this string fileName)
{
string text = File.ReadAllText(dataPath + fileName);
Dictionary<string, ObservableCollection<T>> data = JsonConvert.DeserializeObject<Dictionary<string, ObservableCollection<T>>>(text);
return data;
}
旁注:返回类型Dictionary<string, ObservableCollection<T>>
,因为我需要在json
文件中维护表声明。如果我可以在没有这个的情况下保持"TableName" : [{Table}]
格式,那么我将不胜感激。
简而言之,我遇到的问题与DataGrid
何时发布更新有关。根据一些相关问题,我为 Enemy
类创建了一个空构造函数。一旦我在EnemyGrid
的Name
字段中键入第一个字符,集合就会尝试更新,并且我获得了Enemy
类上大多数属性的默认值。
另请注意,尽管我已经在列上设置了UpdateSourceTrigger=Explicit
,但一旦我开始键入,集合就会继续更新。理想情况下,我希望在完成row
中添加值后创建对象,但是一旦编辑了cell
,就会进行更新。
如何使DataGrid
等待执行此更新,以便在创建对象时拥有所有必需的参数?
有什么直接的方法可以做你想做的事情。如果唯一的选择是在数据网格中进行编辑,则可能需要为数据创建一个与Enemy
具有相同属性的EnemyViewModel
,但每个属性都可为空。
因此,如果您的Enemy
如下所示:
public class Enemy
{
public string Name { get; set; }
public int Level { get; set; }
public Role Role { get; set; }
}
。您的EnemyViewModel
如下所示:
public class EnemyViewModel
{
public string Name { get; set; }
public int? Level { get; set; }
public Role? Role { get; set; }
}
这样,表行中所有内容的默认值都将null
,这将对用户显示为空白/未填充。
一个简单的 LINQ 查询将允许您将从 JSON 读取的敌人转换为ObservableCollection<EnemyViewModel>
:
EnemyGrid.DataContext =
new ObservableCollection<EnemyViewModel>(
enemies.Select(x => new EnemyViewModel { Name = x.Name, Level = x.Level, Role = x.Role }));
但是,问题在于未填充的值不会在其周围显示一个红色框。因此,如果您有某种"保存"或"提交"按钮,则需要检查视图模型项中的空白值,并向用户发出警告以解决此问题。
如果您不是绝对需要在数据网格中进行编辑,则可以仅将其用于显示数据,并创建一个小表单,每个字段都有自己的标签和文本框(或任何最有意义的输入小部件)。当用户提交此内容时,您将将其添加到可观察集合中,并且表将自动更新。这将需要更多的工作,但可以让您更好地控制用户界面,并可能带来更好的用户体验。