我有一个由Observable Dictionary集合支持的DataGrid。我想通过网格进行编辑,目前用户界面似乎不允许这样做。我还观察到,当将IEditableObject接口添加到Dictionary时,单击单元格时会调用接口方法,但UI本身没有任何反应。
这是我的最低范例:
class MainWindowViewModel
{
public MainWindowViewModel() {
ItemsSource = new ObservableCollection<DataGridData> {
new DataGridData() {{"Name", "Abe"},{"Age", "50"},{"Gender", "Male"}},
new DataGridData() {{"Name", "Shelly"},{"Age", "20"},{"Gender", "Female"}
}
};
}
public ObservableCollection<DataGridData> ItemsSource { get; set; }
}
public class DataGridData : Dictionary<string, string>, IEditableObject {
public void BeginEdit(){}
public void CancelEdit(){}
public void EndEdit(){}
}
public partial class MainWindow {
public MainWindow() {
DataContext = new MainWindowViewModel();
InitializeComponent();
foreach (var col in ViewModel.ItemsSource[0].Keys) {
AddColumns(col, col);
}
}
MainWindowViewModel ViewModel {
get { return DataContext as MainWindowViewModel; }
}
void AddColumns(string id, string name)
{
FrameworkElementFactory textBlock = new FrameworkElementFactory(typeof(TextBlock));
textBlock.SetValue(TextBlock.PaddingProperty, new Thickness(2));
textBlock.SetValue(TextBlock.TextProperty, new Binding(string.Format("[{0}]", id)));
Binding textDecorationBinding = new Binding();
textDecorationBinding.ElementName = "DataGrid";
textDecorationBinding.Path = new PropertyPath("DataContext.TextDecoration");
textBlock.SetValue(TextBlock.TextDecorationsProperty, textDecorationBinding);
DataTemplate cellTemplate = new DataTemplate();
cellTemplate.VisualTree = textBlock;
DataGridTemplateColumn column = new DataGridTemplateColumn();
column.Header = name;
column.SortMemberPath = name;
column.CellTemplate = cellTemplate;
DataGrid.Columns.Add(column);
}
}
<Window x:Class="Datagrid.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid
Name="DataGrid"
ItemsSource="{Binding ItemsSource}"
AutoGenerateColumns="False"
>
</DataGrid>
</Grid>
</Window>
使用字典是因为我在编译时没有关于列数据的任何内容。上面的ItemsSource只是一个例子,但我可以在运行时拥有任意数量的键/值。
启用编辑单元格数据需要进行哪些更改?
修改 我从未使用它,但我正在阅读使用反射来发出可以替换字典键/值的实际类。除非有人提出相反的建议,否则我可以试一试。
答案 0 :(得分:0)
在我的选择中,你的代码有点曲折&#34;。实际上,我不会使用Dictionary作为我想要处理的对象的模型。在我看来,最好使用专门的类(这样你就可以实现&#34;着名的&#34; INotifyPropertyChanged
接口)。
例如,您可以使用Person类(这里是一个非常快速的实现):
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Genders Gender { get; set; }
}
您可以实施IEditableObject
,但这不是强制性的。
最后(但并非最不重要)如果我是你,我会在我的XAML中声明DataGrid列而不是我的代码(我无法在你的情况下看到使用代码的正当理由;我不会&#39 ; t知道你可能需要动态列。在这种情况下,你可以阅读这个非常好的article)。
所以我的ViewModel是(您可以轻松地将Dictionary
替换为Person
类):
public class MainWindowViewModel
{
public MainWindowViewModel()
{
People = new ObservableCollection<Dictionary<string, string>> {
new Dictionary<string, string>() {{"Name", "Abe"}, {"Age", "50"}, {"Gender", "Male"}},
new Dictionary<string, string>() {{"Name", "Shelly"}, {"Age", "20"}, {"Gender", "Female"}}
};
}
public ObservableCollection<Dictionary<string, string>> People { get; private set; }
}
我的XAML(如果您使用Person替换Dictionary,请从列出价中删除方括号):
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<StackPanel Orientation="Vertical">
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Path=People}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Path=[Name]}" Header="Name" Width="2*" />
<DataGridTextColumn Binding="{Binding Path=[Age]}" Header="Age" Width="*" />
<DataGridTextColumn Binding="{Binding Path=[Gender]}" Header="Gender" Width="*" />
</DataGrid.Columns>
</DataGrid>
</StackPanel>
</Window>
我的窗口代码隐藏:
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
}
}
通过这种方式,一切正常,您可以使用DataGrid
编辑数据。
我希望这个样本可以帮到你。
修改强>
如果您需要使用自己的方法,可能需要使用AddColumns
方法来宣告CellEditingTemplate
。你的方法将成为:
private void AddColumns(string id, string name)
{
FrameworkElementFactory textBlock = new FrameworkElementFactory(typeof(TextBlock));
textBlock.SetValue(TextBlock.PaddingProperty, new Thickness(2));
textBlock.SetValue(TextBlock.TextProperty, new Binding(String.Format("[{0}]", id)));
FrameworkElementFactory textBox = new FrameworkElementFactory(typeof(TextBox));
textBox.SetValue(TextBox.PaddingProperty, new Thickness(2));
textBox.SetValue(TextBox.TextProperty, new Binding(String.Format("[{0}]", id)));
Binding textDecorationBinding = new Binding();
textDecorationBinding.ElementName = "DataGrid";
textDecorationBinding.Path = new PropertyPath("DataContext.TextDecoration");
textBlock.SetValue(TextBlock.TextDecorationsProperty, textDecorationBinding);
DataTemplate cellTemplate = new DataTemplate();
cellTemplate.VisualTree = textBlock;
DataTemplate cellEditingTemplate = new DataTemplate();
cellEditingTemplate.VisualTree = textBox;
DataGridTemplateColumn column = new DataGridTemplateColumn();
column.Header = name;
column.SortMemberPath = name;
column.CellTemplate = cellTemplate;
column.CellEditingTemplate = cellEditingTemplate;
DataGrid.Columns.Add(column);
}
我读到你正在考虑使用反射来发出一个可以替换字典键/值的实际类。当然这是一个解决方案,但我建议考虑ICustomTypeDescriptor或CustomTypeDescriptor。