Datagrid/WPF - 枚举类型显示异常问题

3

问题

当我尝试在WPF数据网格中显示一个枚举类型时,自动分配的组合框不会正确显示。

当数据网格首次显示时,“enum”根本没有显示出来,而其他类型(如“bool”和“double”)则按预期显示:

Before editing

但如果我点击枚举单元格,就会看到组合框出现:

After editing

如何立即让组合框出现?

定义

在我的确切情况中,我只想显示PathSettings列表。

PathSetting只是一堆像这样定义的数据:

public class PathSettings
{
    public bool IsSelected { get; set; }
    public PathType PathType { get; set; }
    public double Gain { get; set; }
}

其中PathType是一些枚举值:

public enum PathType
{
    Direct,
    Amplified,
    Load
}

假设我想要展示下列列表:

var tests = new List<PathSettings>
{
    new PathSettings { IsSelected = false, PathType = PathType.Direct, Gain = 2.0 },
    new PathSettings { IsSelected = true, PathType = PathType.Amplified, Gain = 2.5 },
    new PathSettings { IsSelected = false, PathType = PathType.Load, Gain = 0.9 },
};

编码试图

我首先创建了一个 ViewAdapter 类,将我的 List 转换为一些 DataView 对象:

public class ViewAdapter
{
    private static IEnumerable<PathSettings> buildDummyEntries()
    {
        return new List<PathSettings>
        {
            new PathSettings { IsSelected = false, PathType = PathType.Direct, Gain = 2.0 },
            new PathSettings { IsSelected = true, PathType = PathType.Amplified, Gain = 2.5 },
            new PathSettings { IsSelected = false, PathType = PathType.Load, Gain = 0.9 },
        };
    }

    public ViewAdapter() : this(buildDummyEntries())
    {

    }
    public ViewAdapter(IEnumerable<PathSettings> settings)
    {
        if (settings == null) { throw new ArgumentNullException(); }

        // 1) Transform to cell collection
        var cells = new ObservableCollection<ObservableCollection<object>>();
        foreach (var s in settings)
        {
            cells.Add(new ObservableCollection<object>
            {
                s.IsSelected,
                s.PathType,
                s.Gain,                    
            });
        }

        // 2) Transform to datatable
        var dataTable = new DataTable();
        dataTable.Columns.Add("IsSelected", typeof(bool));
        dataTable.Columns.Add("PathType", typeof(PathType));
        dataTable.Columns.Add("Gain", typeof(double));
        foreach (var t in settings)
        {
            dataTable.Rows.Add(dataTable.NewRow());
        }

        // 3) Transform to data view and feed with cells
        Settings = new DataView(dataTable);
        for (var i = 0; i < settings.Count(); i++)
        {
            for (var j = 0; j < cells[i].Count; j++)
            {
                Settings[i][j] = cells[i][j];
            }
        }
    }

    public DataView Settings
    {
        get;
        private set;
    }
}

我使用它来填充我的DataGridItemsSource

<Window x:Class="EnumInDataGrid.MainWindow"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:EnumInDataGrid"

    Title="MainWindow" 

    mc:Ignorable="d"
    d:Height="350" d:Width="525"
    d:DataContext="{d:DesignInstance Type=local:ViewAdapter, IsDesignTimeCreatable=True}" 
    d:DesignHeight="239" d:DesignWidth="308">

    <Window.DataContext>
        <local:ViewAdapter />
    </Window.DataContext>

    <Grid>
        <DataGrid 
            ItemsSource="{Binding Settings}"
            CanUserAddRows="False" 
            CanUserDeleteRows="False" 
            CanUserReorderColumns="False" 
            CanUserResizeRows="False" 
            CanUserSortColumns="False" 
            SelectionMode="Single" 
            SelectionUnit="Cell"/>
    </Grid>

</Window>

你有自定义的网格样式吗? - sll
你是否正在使用AutoGenerateColumns? - MBen
@sll,没有,几乎所有的代码都在上面提供了,你可以从一个简单的新WPF应用程序项目中使用Visual Studio将其包围起来以重现相同的问题。 - CitizenInsane
@MBen,我没有修改AutoGenerateColumns属性,所以它必须保持默认值。 - CitizenInsane
1个回答

3
默认情况下,WPF DataGrid是只读模式,您需要单击单元格才能进行编辑。ComboBox列的只读模板是TextBlock,而编辑模板是ComboBox。

如果您想立即显示ComboBox,请使用包含ComboBox的自定义DataGridTemplateColumn。

至于枚举值为什么不会立即显示出来,我怀疑与您的数据源有关。我进行了快速测试,并发现包含枚举值的自动生成列会正确显示。

确定数据源是否有问题的一种方法是摆脱DataView。DataGrid可以绑定到任何可枚举集合,因此直接将其绑定到你的List而不是创建DataView。

我真的不知道为什么你首先要使用DataView对象。理想情况下,WPF中的集合应该是ObservableCollection,而DataObject应该是实现INotifyPropertyChanged的东西。这确保了当您的集合或属性更改时,UI会自动更新。


非常感谢,直接绑定到PathSettings列表解决了问题。 - CitizenInsane
我一开始使用DataView的原因是我对WPF比较陌生,只是复制粘贴了一些我看到的示例。一开始我并不太关心如何从集合中更新UI(同时担心这可能会导致问题),但这是非常有价值的指导,告诉我如何做到这一点。再次感谢。 - CitizenInsane
@CitizenInsane 没问题,很高兴那个方法起作用了 :) 如果你是 WPF 的新手,我强烈建议你学习 MVVM 设计模式。它非常适合 WPF 的绑定系统,并将 UI 与业务逻辑分离。如果你感兴趣,我在这里写了一个简单的介绍:http://rachel53461.wordpress.com/2011/05/08/simplemvvmexample/ - Rachel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接