WPF datagrid will only allow user to add 1 row

2019-09-09 20:50发布

问题:

I have a DataGrid which I initialized with one list item from an ObservableCollection. I would like to allow the user to complete the rest of the datagrid. I have CanUserAddRows=true; I have two textboxes which are enabled/disabled with checkboxes. After filling out the second row, it will not add additional rows unless you double click in one of the cells next to a checkbox(not in the checkbox). It will then put all the number values to 0 and empty any strings and move the current row values to the next row. I would ideally like to add a new empty row by clicking a button, but would settle for a new row by pushing enter.

<Window x:Class="Tourny2.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:Tourny2"
    mc:Ignorable="d"
    Title="Structure Entry" Height="300" Width="804" FontFamily="Verdana" FontSize="16">
<Grid Margin="0,0,0,0">
    <DataGrid x:Name="dataGrid" CanUserAddRows="True" HeadersVisibility="Column" AutoGenerateColumns="False" Background="#FFCEE8E5" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" CanUserSortColumns="False" CanUserReorderColumns="False" FrozenColumnCount="1" ClipToBounds="True">
        <DataGrid.Columns>
            <DataGridTemplateColumn  Header="Levels">
                <DataGridTemplateColumn.CellTemplate >
                    <DataTemplate >
                        <TextBox x:Name="levelEntry"  Width="Auto" Text="{Binding LevelName}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn Header="Use Antes" >
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <CheckBox x:Name="useAntes" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,5,6" Checked="useAntes_Checked" Unchecked="useAntes_Unchecked" IsChecked="{Binding IsActive}"></CheckBox>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn x:Name="EnterAntes" Header="Antes">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBox x:Name="antesEntry" Width="Auto" IsEnabled="False" KeyDown="antesEntry_KeyDown" Text="{Binding Antes}" Loaded="antesEntry_Loaded"></TextBox>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn Header="Small Blind">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBox x:Name="SBEntry" Width="Auto" KeyDown="SBEntry_KeyDown" Text="{Binding SmallBlind}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn Header="Big Blind">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBox x:Name="BBEntry" Width="Auto" KeyDown="BBEntry_KeyDown" Text="{Binding BigBlind}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn Header="Level Time">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBox x:Name="levelTimeEntry" Width="Auto" KeyDown="levelTime_KeyDown"  Text="{Binding LevelTime}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn Header="List Games" >
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <CheckBox x:Name="listGames" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,5,6" Checked="listGames_Checked" Unchecked="listGames_Unchecked" IsChecked="{Binding IsActive}"></CheckBox>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn Header="Current Game">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBox x:Name="gameEntry" Width="Auto" IsEnabled="False"  Text="{Binding CurrentGame}" Loaded="gameEntry_Loaded"></TextBox>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
    <Button x:Name="SaveStructure" Content="Save" HorizontalAlignment="Left" Margin="719,0,0,235" VerticalAlignment="Bottom" Width="75" Click="button_Click" Height="35"/>
</Grid>

namespace Tourny2
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
    private TextBox antesEntry;        
    private TextBox gameEntry;

    public Window1()
    {
        InitializeComponent();

        ObservableCollection<Level> levels = new ObservableCollection<Level>();
        levels.Add(new Level() { LevelName = "Level 1", UseAntes = false, SmallBlind = 25, BigBlind = 50, LevelTime = 20, ListGames = false } );
        dataGrid.ItemsSource = levels;
    }

    private void dataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {

    }
    private void antesEntry_Loaded(object sender, RoutedEventArgs e)
    {
        antesEntry = (sender as TextBox);            
    }
    private void gameEntry_Loaded(object sender, RoutedEventArgs e)
    {
        gameEntry = (sender as TextBox);
    }
    private void useAntes_Checked(object sender, RoutedEventArgs e)
    {
        CheckBox c = (sender as CheckBox);
        if (c.IsChecked == true)
        {
            antesEntry.IsEnabled = true;               
        }
    }
    private void listGames_Checked(object sender, RoutedEventArgs e)
    {
        CheckBox c = (sender as CheckBox);
        if (c.IsChecked == true)
        {
            gameEntry.IsEnabled = true;               
        }
    }
    private void useAntes_Unchecked(object sender, RoutedEventArgs e)
    {
        CheckBox c = (sender as CheckBox);
        if (c.IsChecked == false)
        {
            antesEntry.IsEnabled = false;
        }
    }
    private void listGames_Unchecked(object sender, RoutedEventArgs e)
    {
        CheckBox c = (sender as CheckBox);
        if (c.IsChecked == false)
        {
            gameEntry.IsEnabled = false;

        }
    }
    private void antesEntry_KeyDown(object sender, KeyEventArgs e)          //allow only digits (keyboard and numbers pad)
    {                                                                       //tab and backspace to be entered in antes
        int key = (int)e.Key;
        e.Handled = !(key >= 34 && key <= 43 ||
         key >= 74 && key <= 83 || key == 2);
        if (e.Key == Key.Tab)
        {
            e.Handled = false;
        }
    }
    private void SBEntry_KeyDown(object sender, KeyEventArgs e)          //allow only digits (keyboard and numbers pad)
    {                                                                       //tab and backspace to be entered in SB
        int key = (int)e.Key;
        e.Handled = !(key >= 34 && key <= 43 ||
         key >= 74 && key <= 83 || key == 2);
        if(e.Key == Key.Tab|| e.Key == Key.Enter)
        {
            e.Handled = false;
        }           
    }
    private void BBEntry_KeyDown(object sender, KeyEventArgs e)          //allow only digits (keyboard and numbers pad)
    {                                                                       //tab and backspace to be entered in BB
        int key = (int)e.Key;
        e.Handled = !(key >= 34 && key <= 43 ||
         key >= 74 && key <= 83 || key == 2);
        if (e.Key == Key.Tab)
        {
            e.Handled = false;
        }
    }
    private void levelTime_KeyDown(object sender, KeyEventArgs e)          //allow only digits (keyboard and numbers pad)
    {                                                         
                 //tab,and backspace to be entered in Level Time
        int key = (int)e.Key;
        e.Handled = !(key >= 34 && key <= 43 ||
         key >= 74 && key <= 83 || key == 2);
        if (e.Key == Key.Tab||e.Key == Key.Enter)
        {
            e.Handled = false;
        }
    }

    private void button_Click(object sender, RoutedEventArgs e)
    {
        dataGrid.SelectAllCells();
        dataGrid.ClipboardCopyMode = DataGridClipboardCopyMode.ExcludeHeader;
        ApplicationCommands.Copy.Execute(null, dataGrid);
        dataGrid.UnselectAllCells();
        String result = (string)Clipboard.GetData(DataFormats.CommaSeparatedValue);
        Clipboard.Clear();
        using (StreamWriter file = new StreamWriter("..\\TestStructure.csv"))
            {
                file.WriteLine(result);
            }
        }
    }        
}

namespace Tourny2
{
 public class Level : INotifyPropertyChanged
{
    private string levelName = "";                      //declare some fields
    private bool useAntes = false;
    private int antes;                              
    private int smallBlind = 0;
    private int bigBlind = 0;
    private double levelTime = 0;
    private bool listGames = false;
    private string currentGame;

    public string LevelName                             //create properties for the fields       
    {
        get { return this.levelName; }

        set
        {
            if (this.levelName != value)
            {
                this.levelName = value;
                this.NotifyPropertyChanged("LevelName");
            }
        }
    }    
    public bool UseAntes
    {
        get { return this.useAntes; }
        set
        {
            if (this.useAntes != value)
            {
                this.useAntes = value;
                this.NotifyPropertyChanged("UseAntes");
            }
        }
    }
    public int Antes
    {                               
        get { return (int)antes; }
        set
        {
            if (this.antes != value)
            {
                this.antes = value;
                this.NotifyPropertyChanged("Antes");
            }
        }
    }
    public int SmallBlind
    {
        get { return this.smallBlind; }
        set
        {
            if (this.smallBlind != value)
            {
                this.smallBlind = value;
                this.NotifyPropertyChanged("SmallBlind");
            }
        }
    }
    public int BigBlind
    {
        get { return this.bigBlind; }
        set
        {
            if (this.bigBlind != value)
            {
                this.bigBlind = value;
                this.NotifyPropertyChanged("BigBlind");
            }
        }
    }
    public double LevelTime
    {
        get { return this.levelTime; }
        set
        {
            if (this.levelTime != value)
            {
                this.levelTime = value;
                this.NotifyPropertyChanged("LevelTime");
            }
        }
    }
    public bool ListGames
    {
        get { return this.listGames; }
        set
        {
            if (this.listGames != value)
            {
                this.listGames = value;
                this.NotifyPropertyChanged("ListGames");
            }
        }
    }
    public string CurrentGame
    {
        get { return this.currentGame; }
        set
        {
            if (this.currentGame != value)
            {
                this.currentGame = value;
                this.NotifyPropertyChanged("CurrentGame");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged(string propName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }       
    public Level()
    {
        this.levelName = levelName;
        this.useAntes = useAntes;
        this.antes = antes;
        this.smallBlind = smallBlind;
        this.bigBlind = bigBlind;
        this.levelTime = levelTime;
        this.listGames = listGames;
        this.currentGame = currentGame;
    }

回答1:

You can add blank rows by adding the following codes to data grid key up event.

if(e.Key == Key.Enter)
{
   AddNewRow();
}

Now, implement the AddNewRow method as below.

private void AddNewRow()
{
   TestItemList.Add(new TestItem());
   gvTest.ItemsSource = TestItemList;
}

Here you add blank rows by just press enter on the data grid. According to the previous answer, I declared Observable collection instance as global instance so simply adding the above-mentioned code you can add blank rows.

Hope this helps you.