【问题标题】:WPF DataGrid with only one combobox in templatecolumn not adding new rows模板列中只有一个组合框的 WPF DataGrid 不添加新行
【发布时间】:2014-04-25 14:40:47
【问题描述】:

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

我的视图模型:

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));
    }
}
}

“域”类:

杂货项目:

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

【问题讨论】:

    标签: wpf wpfdatagrid


    【解决方案1】:
    <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding GroceryItems}"/>
    

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

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

    这会将每个 GroceryItemType 的名称插入到 ComboBox 中关联的 GroceryItem 中。由于您确实将其指定为 ItemsSource,因此您最终可能会在 ComboBox 中仅拥有 GroceryItemType 的名称。我认为这不是您想要的,但现在,我看不到更多代码来了解您想要存档的内容。

    请注意,如果您想将更改反映到 ViewModel,您将必须在两个模型(GroceryItemGroceryItemType)中实现 INotifyPropertyChanged,反之亦然。这就是Mode=TwoWay 派上用场的地方。

    【讨论】:

    • 我只是想通知您,您建议的数据绑定方式不起作用。如果我按照您建议的方式进行数据绑定,则甚至不会显示现有项目的类型(在 MainWindowViewModel 的 ctor 中构造),并且所有组合框都不包含任何值。此外,我的示例代码很少,因为我想构建一个可以重现问题的最小示例。
    • 那你好像做错了什么。但是,如果您不提供任何进一步的代码来证明这一点,我将无法帮助您。据我从您的回答中可以看出,您已经在使用我的建议并且确实有效。
    【解决方案2】:

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

    要使其正常工作,您必须在要编辑的单元格中点击多次次,然后从中跳出标签以添加新行。 p>

    所以视图的更新代码如下所示:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-30
      • 2013-01-23
      • 1970-01-01
      • 2014-12-03
      • 1970-01-01
      • 2015-04-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多