按Enter或Tab键,Datagrid不添加新行

时间:2014-04-09 13:35:19

标签: c# wpf xaml datagrid

我有一个数据网格,其中CanUserAddRows = "true"

当我运行程序时,我得到一个空行。当我在该行输入数据时,它的效果非常好。但之后如果我尝试添加新行,我就无法添加它,因为按 Enter TAB 我没有得到空行。

这是我的数据网格所在的页面:

<Page x:Class="WPF_Client.Pages.Masters.Multiple.Groups"
      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:helpers="clr-namespace:WPF_Client.HelperClasses"
      xmlns:vm="clr-namespace:WPF_Client.ViewModels.Masters.Multiple"
      mc:Ignorable="d" 
      d:DesignHeight="760" d:DesignWidth="1366"
      Title="Groups">

    <Page.DataContext>
        <vm:GroupsViewModel />
    </Page.DataContext>

    <Page.Resources>
        <CollectionViewSource x:Key="GroupNamesWithCorrespondingEffectsCollection" Source="{Binding GroupNamesWithCorrespondingEffects}" />
    </Page.Resources>

    <Grid>
        <DataGrid CanUserAddRows="True" CanUserReorderColumns="False" CanUserSortColumns="False" CanUserDeleteRows="True"
                  ItemsSource="{Binding Groups}" AutoGenerateColumns="False">
            <DataGrid.Resources>
                <CompositeCollection x:Key="Items">
                    <ComboBoxItem IsEnabled="False" Background="#FF2A2A2A" Foreground="White">
                        <Grid TextElement.FontWeight="Bold" >
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition SharedSizeGroup="A" />
                                <ColumnDefinition Width="50" />
                                <ColumnDefinition SharedSizeGroup="B" />
                            </Grid.ColumnDefinitions>
                            <Grid.Children>
                                <TextBlock Grid.Column="0" Text="Group Name" />
                                <TextBlock Grid.Column="2" Text="Effect" />
                            </Grid.Children>
                        </Grid>
                    </ComboBoxItem>
                    <CollectionContainer Collection="{Binding Source={StaticResource GroupNamesWithCorrespondingEffectsCollection}}" />
                </CompositeCollection>

                <DataTemplate DataType="{x:Type helpers:GroupNameWithCorrespondingEffect}">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition SharedSizeGroup="A" />
                            <ColumnDefinition Width="50" />
                            <ColumnDefinition SharedSizeGroup="B" />
                        </Grid.ColumnDefinitions>
                        <Grid.Children>
                            <TextBlock Grid.Column="0" Text="{Binding GroupName}" />
                            <TextBlock Grid.Column="2" Text="{Binding CorrespondingEffect}" />
                        </Grid.Children>
                    </Grid>
                </DataTemplate>
            </DataGrid.Resources>
                <DataGrid.Columns>
                <DataGridTemplateColumn Header="Name" Width="2*">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBox Text="{Binding GroupName}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTemplateColumn Header="Group" Width="2*">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox ItemsSource="{DynamicResource Items}" 
                                      SelectedValue="{Binding DataContext.SelectedGroupID, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Page}}}"
                                      SelectedValuePath="GroupID" Grid.IsSharedSizeScope="True" TextSearch.TextPath="GroupName">
                            </ComboBox>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTemplateColumn Header="Effect" Width="*" >
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox ItemsSource="{Binding DataContext.Effects, RelativeSource={RelativeSource AncestorType={x:Type Page}}}" DisplayMemberPath="Effect" 
                                                            SelectedValue="{Binding DataContext.SelectedEffectID, RelativeSource={RelativeSource AncestorType={x:Type Page}}}" SelectedValuePath="EffectID"
                                      Visibility="{Binding Path=DataContext.SelectedGroupID, 
                                                             RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Page}},
                                                             Converter={StaticResource effectsVisibilityConverter}}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>

</Page>

这是我的ViewModel:

public class GroupsViewModel : ViewModelBase, IModule
{
    public GroupsViewModel()
    {
        SessionViewModel.Instance.ModulesOpen.Add((IModule)this);

        Groups = new ObservableCollection<Group>();

        using (Entities db = new Entities())
        {
            List<GroupNameWithCorrespondingEffect> _GroupNamesWithCorrespondingEffects = (
                                                                                             from g in db.Groups
                                                                                             select new GroupNameWithCorrespondingEffect
                                                                                             {
                                                                                                 GroupID = g.GroupID,
                                                                                                 GroupName = g.GroupName,
                                                                                                 CorrespondingEffect = g.Master_Effects.Effect
                                                                                             }
                                                                                         ).ToList();

            GroupNamesWithCorrespondingEffects
                = new ObservableCollection<GroupNameWithCorrespondingEffect>(
                                                                                _GroupNamesWithCorrespondingEffects.Where
                                                                                    (
                                                                                        u => !StaticMethods.GetAllChildren(25)
                                                                                                .Select(x => x.GroupID)
                                                                                                .Contains(u.GroupID)
                                                                                    ).ToList()
                                                                            );

            Effects = new ObservableCollection<Master_Effects>(from m in db.Master_Effects
                                                               select m);
        }
    }

    ~GroupsViewModel()
    {
        SessionViewModel.Instance.ModulesOpen.Remove((IModule)this);
    }

    private ObservableCollection<Group> _groups;
    public ObservableCollection<Group> Groups
    {
        get
        {
            return _groups;
        }
        set
        {
            _groups = value;
            OnPropertyChanged("Groups");
        }
    }

    private ObservableCollection<GroupNameWithCorrespondingEffect> _groupNamesWithCorrespondingEffects;
    public ObservableCollection<GroupNameWithCorrespondingEffect> GroupNamesWithCorrespondingEffects
    {
        get
        {
            return _groupNamesWithCorrespondingEffects;
        }
        set
        {
            _groupNamesWithCorrespondingEffects = value;
            OnPropertyChanged("GroupNamesWithCorrespondingEffects");
        }
    }

    private int _selectedGroupID;
    public int SelectedGroupID
    {
        get
        {
            return _selectedGroupID;
        }
        set
        {
            _selectedGroupID = value;
            OnPropertyChanged("SelectedGroupID");
        }
    }

    private ObservableCollection<Master_Effects> _effects;
    public ObservableCollection<Master_Effects> Effects
    {
        get
        {
            return _effects;
        }
        set
        {
            _effects = value;
            OnPropertyChanged("Effects");
        }
    }

    private int _selectedEffectID;
    public int SelectedEffectID
    {
        get
        {
            return _selectedEffectID;
        }

        set
        {
            _selectedEffectID = value;
            OnPropertyChanged("SelectedEffectID");
        }
    }

    public string ModuleFriendlyName
    {
        get { return "GroupsViewModel"; }
    }

    public string ModuleName
    {
        get { return "Groups"; }
    }
}

我做错了吗?或者它是dataGrid的默认行为?

更新

我根据您的建议更新了我的代码。这是我的xaml:

<DataGrid ..............>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="PreviewKeyDown">
            <i:InvokeCommandAction Command="{Binding DataContext.NewRowCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Page}}}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</DataGrid>

这是我的ViewModel:

//在构造函数中: NewRowCommand = new RelayCommand(NewRow);

//在身体:

public ICommand NewRowCommand { get; set; }

private void NewRow(object obj)
{
    MessageBox.Show("PreviewKeyDown on Datagrid invoked.");
}

当我在DataGrid的输入区域按任意键时,我成功地在输出中获取了MessageBox。

更新后的问题:

现在,在尝试了你的建议点之后,我也遇到了一些问题。

我只想在按 Enter 时显示该消息框(如果它是网格上的默认行为。我不知道默认行为,因为我对DataGrid很新。)key在DataGrid上。所以,我的实际问题是识别按下的键。

1 个答案:

答案 0 :(得分:1)

您必须将键击事件“路由”到某个ViewModel方法,该方法将新项目添加到集合中。在这种方法结束时,您必须调用OnPropertyChanged以反映视图中的新项目。

修改

  1. 引用程序集System.Windows.Interactivity
  2. xmlns:i =“clr-namespace:System.Windows.Interactivity; assembly = System.Windows.Interactivity”添加到您的xaml声明中
  3. 使用它:
  4. <i:Interaction.Triggers> <i:EventTrigger> </i:EventTrigger> </i:Interaction.Triggers>

    更多细节请看这个链接:

    Here here

    编辑2:

      

    我看到了问题,InputBindings将在这种情况下完成工作:

    <DataGrid.InputBindings>
        <KeyBinding Key="Enter" Command="{Binding NewRowCommand }"/>
    </DataGrid.InputBindings>