我有一个JSON模型,在那儿有一个IList下属。
没什么特别的,我想将它们放入一个数据网格中,用户可以在其中添加和删除列表中的值。
所以我首先遇到唯一的长度列问题,因为显然C#觉得选择属性很有趣,而恰好是长度。
所以我通过另一个stackoverflow解决了这个问题。
<DataGrid ItemsSource="{Binding Path=Job.Subordinates, UpdateSourceTrigger=PropertyChanged}" ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" Height="Auto" HorizontalAlignment="Left" Grid.Column="1" AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTemplateColumn Header="Subordinate Id">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"></TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
但是现在最终结果是一个只读的DataGrid。如果加载JSON,则无法添加新行或编辑现有行。
为什么会发生这种现象?
编辑:带有其字段的json对象
using GalaSoft.MvvmLight;
using System;
using System.Collections.Generic;
namespace GalaxyCreator.Model.Json
{
public class Job : ObservableObject
{
private String _id;
public String Id
{
get { return _id; }
set
{
Set(ref _id, value);
}
}
private String _name;
public String Name
{
get { return _name; }
set
{
Set(ref _name, value);
}
}
private Boolean _startActive;
public Boolean StartActive
{
get { return _startActive; }
set
{
Set(ref _startActive, value);
}
}
private Boolean _disabled;
public Boolean Disabled
{
get { return _disabled; }
set
{
Set(ref _disabled, value);
}
}
private Boolean _rebuild;
public Boolean Rebuild
{
get { return _rebuild; }
set
{
Set(ref _rebuild, value);
}
}
private Boolean _comandeerable;
public Boolean Commandeerable
{
get { return _comandeerable; }
set
{
Set(ref _comandeerable, value);
}
}
private Boolean _subordinate;
public Boolean Subordinate
{
get { return _subordinate; }
set
{
Set(ref _subordinate, value);
}
}
private bool _buildatshipyard = true;
public bool Buildatshipyard
{
get { return _buildatshipyard; }
set
{
Set(ref _buildatshipyard, value);
}
}
private JobLocation _jobLocation = new JobLocation();
public JobLocation JobLocation
{
get { return _jobLocation; }
set
{
Set(ref _jobLocation, value);
}
}
private JobCategory _jobCategory = new JobCategory();
public JobCategory JobCategory
{
get { return _jobCategory; }
set
{
Set(ref _jobCategory, value);
}
}
private JobQuota _jobQuota = new JobQuota();
public JobQuota JobQuota
{
get { return _jobQuota; }
set
{
Set(ref _jobQuota, value);
}
}
private IList<JobOrder> _orders = new List<JobOrder>();
public IList<JobOrder> Orders
{
get { return _orders; }
set
{
Set(ref _orders, value);
}
}
private String _basket;
public String Basket
{
get { return _basket; }
set
{
Set(ref _basket, value);
}
}
private String _encounters;
public String Encounters
{
get { return _encounters; }
set
{
Set(ref _encounters, value);
}
}
private String _time;
public String Time
{
get { return _time; }
set
{
Set(ref _time, value);
}
}
private Ship _ship = new Ship();
public Ship Ship
{
get { return _ship; }
set
{
Set(ref _ship, value);
}
}
private IList<String> _subordinates = new List<String>();
public IList<String> Subordinates
{
get { return _subordinates; }
set
{
Set(ref _subordinates, value);
}
}
}
}
编辑:我尝试了一种新方法,但还是没有运气,这次我尝试包装String
包装器
public class SubordinateItem : ObservableObject
{
private String _value = default(String);
public SubordinateItem(string subordinate)
{
this._value = subordinate;
}
public String Value
{
get { return _value; }
set
{
if (value != _value)
{
_value = value;
Set(ref _value, value);
}
}
}
}
ViewModel
class JobEditorDetailViewModel : DialogViewModelBase
{
public Job Job { get; set; }
private ObservableCollection<SubordinateItem> _subordinateItems = new ObservableCollection<SubordinateItem>();
public ObservableCollection<SubordinateItem> SubordinateItems
{
get { return _subordinateItems; }
set
{
this.Job.Subordinates.Clear();
foreach (SubordinateItem item in value)
{
this.Job.Subordinates.Add(item.Value);
}
Set(ref _subordinateItems, value);
}
}
public JobEditorDetailViewModel(string message, Job job) : base(message)
{
this.Job = job;
this._saveCommand = new RelayCommand<object>((parent) => OnSaveClicked(parent));
this._cancelCommand = new RelayCommand<object>((parent) => OnCancelClicked(parent));
foreach(String subordinate in Job.Subordinates)
{
_subordinateItems.Add(new SubordinateItem(subordinate));
}
}
}
XAML
<DataGrid ItemsSource="{Binding SubordinateItems, NotifyOnTargetUpdated=True}" ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Auto" Height="Auto" Grid.Row="1" AutoGenerateColumns="False" HorizontalAlignment="Left" Width="572" >
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Value, UpdateSourceTrigger=PropertyChanged}" Width="500" Header="Subordinate Id" IsReadOnly="false" />
</DataGrid.Columns>
</DataGrid>
答案 0 :(得分:0)
因此,在写了各种hack尝试并修复它的漫长会议之后,我得到了以下设置的解决方案
public class SubordinateItem : ObservableObject
{
private String _value = default(String);
public SubordinateItem() { }
public SubordinateItem(string subordinate)
{
this._value = subordinate;
}
public String Value
{
get { return _value; }
set
{
if (value != _value)
{
_value = value;
Set(ref _value, value);
}
}
}
}
请注意没有参数的公共构造函数,这是能够将新项添加到数据网格所必需的。没有它,它将无法为其实例化新对象。这是视图模型
class JobEditorDetailViewModel : DialogViewModelBase
{
public Job Job { get; set; }
private RelayCommand<object> _saveCommand = null;
public RelayCommand<object> SaveCommand
{
get { return _saveCommand; }
set { _saveCommand = value; }
}
private RelayCommand<object> _cancelCommand = null;
public RelayCommand<object> CancelCommand
{
get { return _cancelCommand; }
set { _cancelCommand = value; }
}
private IList<SubordinateItem> _subordinateItems = new List<SubordinateItem>();
public IList<SubordinateItem> SubordinateItems
{
get { return _subordinateItems; }
set
{
Set(ref _subordinateItems, value);
}
}
public JobEditorDetailViewModel(string message, Job job) : base(message)
{
this.Job = job;
this._saveCommand = new RelayCommand<object>((parent) => OnSaveClicked(parent));
this._cancelCommand = new RelayCommand<object>((parent) => OnCancelClicked(parent));
foreach (String subordinate in Job.Subordinates)
{
_subordinateItems.Add(new SubordinateItem(subordinate));
}
}
private void OnSaveClicked(object parameter)
{
this.Job.Subordinates.Clear();
foreach (SubordinateItem item in _subordinateItems)
{
this.Job.Subordinates.Add(item.Value);
}
this.CloseDialogWithResult(parameter as Window, DialogResult.Yes);
}
private void OnCancelClicked(object parameter)
{
this.CloseDialogWithResult(parameter as Window, DialogResult.No);
}
}
因此,在视图模型的构造函数中,我从JSON对象Job.Subordinates中获取数据,该对象是String的IList,并将其包装在SubordinateItem中并存储在_subordinateItems中。数据网格已绑定到此并可以使用。然后,我有一个保存按钮,其后有一个命令,在该按钮中进行反向操作。我将DataGrid在_subordinateItems中拥有的所有内容都放回json对象中。对我来说,似乎没有任何办法将datagrid直接绑定到String的json对象IList
Xaml相关部分
<Label Content="Subordinates" />
<DataGrid ItemsSource="{Binding SubordinateItems, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
Height="Auto" Grid.Row="1"
AutoGenerateColumns="False"
HorizontalAlignment="Left"
Width="572" SelectionMode="Single">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Value, UpdateSourceTrigger=PropertyChanged}" Width="500" Header="Subordinate Id" IsReadOnly="false" />
</DataGrid.Columns>
</DataGrid>