我有一个基本的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
绑定到从ObservableCollection
文件读入的json
:
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
类创建了一个空构造函数。只要在Name
上的EnemyGrid
字段中键入第一个字符,集合就会尝试更新,并且我会获得Enemy
类上大多数属性的默认值。
另请注意,虽然我已经在列上设置了UpdateSourceTrigger=Explicit
,但是一旦我开始输入,该集合就会继续更新。理想情况下,我希望在row
中添加完值后创建对象,但在编辑cell
后进行更新。
如何让DataGrid
等待执行此更新,以便在创建对象时获得所有必需参数?
答案 0 :(得分:2)
我不知道你要做什么的直接方法。如果您唯一的选择是在数据网格中进行修改,则可能需要为与EnemyViewModel
具有相同属性的数据创建Enemy
,但每个属性都可以为空。
所以,如果你的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 }));
但问题是,未填充的值不会在它们周围出现红色框。因此,如果您有某种“保存”或“提交”按钮,则需要检查您的视图模型项是否有空白值,并发出警告以便用户进行修复。
如果您不是绝对需要在数据网格中进行编辑,则可以仅将其用于显示数据并创建一个小表单,每个字段都有自己的标签和TextBox(或任何输入窗口小部件最有意义) 。当用户提交此项时,您将其添加到您的可观察集合中,并且该表将自动更新。这将是一项更多的工作,但会让您更好地控制用户界面,并可以带来更好的用户体验。