WPF4 DataGrid 无法显示或取消编辑枚举列?

发布于 2024-10-21 05:25:59 字数 2239 浏览 0 评论 0原文

我已经尽可能地简化了这个过程。我的窗口中有这个DataGrid

<DataGrid
    x:Name="myDataGrid"
    CanUserAddRows="False" 
    CanUserDeleteRows="False" 
    CanUserReorderColumns="False"
    CanUserSortColumns="False"
    SelectionMode="Single" 
    SelectionUnit="FullRow" 
    GridLinesVisibility="Horizontal"
    ItemsSource="{Binding ValuesDataTable}"
    CellEditEnding="myDataGrid_CellEditEnding"/>

我的DataContext是类ViewModel

enum SomeEnum
{
    Choice1 = 0,
    Choice2
}

class ViewModel
{
    public ViewModel()
    {
        var dataTable = new DataTable();

        var column1 = dataTable.Columns.Add();
        column1.DataType = typeof(string);

        var column2 = dataTable.Columns.Add();
        column2.DataType = typeof(SomeEnum);

        dataTable.Rows.Add(new object[] { "Name 1", SomeEnum.Choice1 });
        dataTable.Rows.Add(new object[] { "Name 2", SomeEnum.Choice2 });

        this.ValuesDataTable = dataTable;

    }

    public DataTable ValuesDataTable { get; private set; }
}

在我的窗口的代码隐藏中,我有这个事件处理程序:

private void myDataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
    if (e.EditAction == DataGridEditAction.Commit)
    {
        var dataGrid = (DataGrid)sender;
        dataGrid.CancelEdit();
    }
}

当我运行应用程序列 1 按预期工作(它正确显示值,我可以开始编辑,当我尝试提交时编辑会取消)。但是,第 2 列不显示值。当您尝试编辑它时,会显示带有两个枚举选项的下拉框,但是当您尝试提交它并执行 CancelEdit 时,WPF 代码中的某处会引发异常并中断绑定。例外是:

System.NotSupportedException:
EnumConverter cannot convert from System.Int32

我认为 DataGrid 正在从 DataTable 读取 Enum 列的值作为 int 并且它可能需要一个字符串。有办法解决这个问题吗?

更新

我发现,如果我处理DataGrid.LoadingRow事件,并且获得ItemData数组,第二列就变成了Int32 而不是枚举。尝试将其转换回正确的类型没有帮助:

private void myDataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
    var row = e.Row.Item as DataRowView;
    var dataRow = row.Row;
    var itemArray = dataRow.ItemArray;

    // BTW, this doesn't help:
    itemArray[1] = (SomeEnum)itemArray[1];
    dataRow.ItemArray = itemArray;
}

I've simplified this as much as possible. I have this DataGrid in my window:

<DataGrid
    x:Name="myDataGrid"
    CanUserAddRows="False" 
    CanUserDeleteRows="False" 
    CanUserReorderColumns="False"
    CanUserSortColumns="False"
    SelectionMode="Single" 
    SelectionUnit="FullRow" 
    GridLinesVisibility="Horizontal"
    ItemsSource="{Binding ValuesDataTable}"
    CellEditEnding="myDataGrid_CellEditEnding"/>

My DataContext is the class ViewModel:

enum SomeEnum
{
    Choice1 = 0,
    Choice2
}

class ViewModel
{
    public ViewModel()
    {
        var dataTable = new DataTable();

        var column1 = dataTable.Columns.Add();
        column1.DataType = typeof(string);

        var column2 = dataTable.Columns.Add();
        column2.DataType = typeof(SomeEnum);

        dataTable.Rows.Add(new object[] { "Name 1", SomeEnum.Choice1 });
        dataTable.Rows.Add(new object[] { "Name 2", SomeEnum.Choice2 });

        this.ValuesDataTable = dataTable;

    }

    public DataTable ValuesDataTable { get; private set; }
}

In my window's code-behind, I have this event handler:

private void myDataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
    if (e.EditAction == DataGridEditAction.Commit)
    {
        var dataGrid = (DataGrid)sender;
        dataGrid.CancelEdit();
    }
}

When I run the application column 1 works as expected (it displays the value properly, I can start an edit, and the edit cancels when I try to commit it). Column 2, however, doesn't display the values. When you try to edit it, the drop down box with the two Enum choices are displayed, but when you try to commit it, and it executes CancelEdit, somewhere in the WPF code it throws an exception and breaks the binding. The exception is:

System.NotSupportedException:
EnumConverter cannot convert from System.Int32

I think that the DataGrid is reading the value of the Enum column from the DataTable as an int and it's probably expecting a string. Is there some way around this?

Update

I found that if I handle the DataGrid.LoadingRow event, and I get the ItemData array, the second column has become an Int32 instead of the enum. Attempts to cast it back to the right type aren't helping:

private void myDataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
    var row = e.Row.Item as DataRowView;
    var dataRow = row.Row;
    var itemArray = dataRow.ItemArray;

    // BTW, this doesn't help:
    itemArray[1] = (SomeEnum)itemArray[1];
    dataRow.ItemArray = itemArray;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

不奢求什么 2024-10-28 05:25:59

我已经弄清楚为什么会发生这种情况。问题出在 DataTable 中,特别是 DataRow 中,而不是在 WPF DataGrid 中。

如果我更改视图模型中向 DataTable 添加一行的行:

var r1 = dataTable.Rows.Add(row1);

...然后检查 r1,特别是 r1.ItemArray[1],它的类型是int,而不是SomeEnum。这意味着它已经丢失了类型信息。

答案似乎是我必须使用我定义的某个类的 ObservableCollection 。如果该类具有枚举的属性类型,则它可以工作。

I've figured out why this is happening. The problem is in the DataTable, specifically the DataRow, not in the WPF DataGrid.

If I change the line in my view model where I add a row to the DataTable:

var r1 = dataTable.Rows.Add(row1);

... and then inspect r1, specifically r1.ItemArray[1], it's of type int, not SomeEnum. That means it's already lost the type information.

The answer seems to be that I have to use an ObservableCollection of some class that I define. If you have a property type of an enum on that class, it works.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文