WPF DataGrid,模板列中只有一个组合框,不添加新行

时间:2014-04-25 14:40:47

标签: wpf wpfdatagrid

我是WPF的新手,所以请为任何“愚蠢”的错误道歉。 我有一个只有一列的数据网格,即一个组合框。数据网格按预期显示一个新的空行。但是如果我在新行上的组合框中选择一个值,则不会添加额外的新行。我已经尝试根据这个答案添加一个编辑模板:datagrid showing one new row, but not any subsequent但是没有任何帮助。

<Window x:Class="WPFSpielplatz.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="clr-namespace:WPFSpielplatz"
    Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
    <d:MainWindowViewModel />
</Window.DataContext>
<Grid>
    <StackPanel HorizontalAlignment="Left" Height="319" VerticalAlignment="Top" Width="517">
        <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding GroceryItems}" CanUserAddRows="True">
            <DataGrid.Columns>
                <DataGridTemplateColumn Header="Combo">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=DataGrid}, Path=DataContext.GroceryItemTypes}" SelectedItem="{Binding GroceryItemType, UpdateSourceTrigger=PropertyChanged}"  DisplayMemberPath="Name" ></ComboBox>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                    <DataGridTemplateColumn.CellEditingTemplate>
                        <DataTemplate>
                            <ComboBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=DataGrid}, Path=DataContext.GroceryItemTypes}" SelectedItem="{Binding GroceryItemType, UpdateSourceTrigger=PropertyChanged}"  DisplayMemberPath="Name" ></ComboBox>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellEditingTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </StackPanel>
</Grid>

我的ViewModel:

using System.Collections.ObjectModel;
using System.ComponentModel;
using WPFSpielplatz.Annotations;

namespace WPFSpielplatz
{
public class MainWindowViewModel:INotifyPropertyChanged 
{
    private ObservableCollection<GroceryItem> _groceryItems;

    public MainWindowViewModel()
    {

        GroceryItemTypes = new ObservableCollection<GroceryItemType>
            {
                new GroceryItemType("Food"),
                new GroceryItemType("Non-Food")
            };

        _groceryItems=new ObservableCollection<GroceryItem>
            {
                new GroceryItem(){GroceryItemType=GroceryItemTypes[0]},
                new GroceryItem(){GroceryItemType=GroceryItemTypes[1]}
            };
    }

    public ObservableCollection<GroceryItem> GroceryItems
    {
        get { return _groceryItems; }
        set
        {
            _groceryItems = value;
            OnPropertyChanged("GroceryItems");
        }
    }

    public ObservableCollection<GroceryItemType> GroceryItemTypes { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}
}

“域名”类:

GroceryItem:

namespace WPFSpielplatz
{
public class GroceryItem
{
    public GroceryItemType GroceryItemType { get; set; }

    public GroceryItem()
    {
    }
}
}

GroceryItemType:

namespace WPFSpielplatz
{
public class GroceryItemType
{
    public GroceryItemType()
    {

    }

    public GroceryItemType(string name)
    {
        Name = name;
    }
    public string Name { get; set; }
}
}

2 个答案:

答案 0 :(得分:0)

<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding GroceryItems}"/>

足以将您的集合绑定到DataGrid。它已经是相对的,但您只需要将GroceryItem类的属性绑定到DataGrid,如下所示:

<ComboBox ItemsSource="{Binding GroceryItemType.Name, Mode=TwoWay"}/>

这会将每个GroceryItemType的名称插入到ComboBox中关联的GroceryItem。您可能最终只在ComboBox中使用GroceryItemType的名称,因为您确实将其指定为ItemsSource。我不认为这是你想要的,但是现在,我没有看到任何更多的代码来理解你想要存档的内容。

请注意,如果您想要反映对ViewModel的更改,并且两个模型(INotifyPropertyChangedGroceryItem必须实施GroceryItemType反之亦然。这就是Mode=TwoWay派上用场的地方。

答案 1 :(得分:0)

好的,我解决了。它一直有效,问题是,我的<DataGridTemplateColumn.CellTemplate>和我的<DataGridTemplateColumn.CellEditingTemplate>看起来一样,所以我可以在没有进入编辑模式的情况下更改组合框中的值。但只有在进入并成功退出编辑模式后,才会向数据网格添加新行。

要实现此功能,您必须在要编辑的单元格中单击多次次,然后单击选项卡以添加新行。

因此,View的更新代码如下所示:

<Window x:Class="WPFSpielplatz.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="clr-namespace:WPFSpielplatz"
    Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
    <d:MainWindowViewModel />
</Window.DataContext>
<Grid>
    <StackPanel HorizontalAlignment="Left" Height="319" VerticalAlignment="Top" Width="517">
        <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding GroceryItems}" CanUserAddRows="True">
            <DataGrid.Columns>
                <DataGridTemplateColumn Header="Combo">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <StackPanel>
                                <TextBlock Text="{Binding Path=GroceryItemType.Name}" ></TextBlock>
                            </StackPanel>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                    <DataGridTemplateColumn.CellEditingTemplate>
                        <DataTemplate>
                            <StackPanel>
                                <TextBlock>Edit</TextBlock>
                                <ComboBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=DataGrid}, Path=DataContext.GroceryItemTypes}" SelectedItem="{Binding GroceryItemType, UpdateSourceTrigger=PropertyChanged}"  DisplayMemberPath="Name" ></ComboBox>
                            </StackPanel>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellEditingTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </StackPanel>
</Grid>