Datagrid / WPF - 枚举类型的奇怪显示行为

时间:2011-11-29 16:59:20

标签: wpf wpfdatagrid

问题

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

首次显示数据网格时,根本不会显示“enum”,而“bool”和“double”等其他类型会按预期显示:

Before editing

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

After editing

如何立即出现组合框?

解释

在我的确切情况下,我只想显示List 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;
    }
}

用我的ItemsSource DataGrid喂它:

<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>

1 个答案:

答案 0 :(得分:3)

默认情况下,WPF DataGrids处于只读模式,您必须单击一个单元格才能编辑它们。 ComboBox列的只读模板是TextBlock,而编辑模板是ComboBox。

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

至于枚举值没有立即显示,我怀疑它与您的数据源有关。我做了一个快速测试,自动生成的包含枚举值的列确实显示正确。

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

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