【问题标题】:Simulate CTRL down until I desire in c#?在 c# 中模拟 CTRL 直到我想要?
【发布时间】:2018-01-24 07:01:23
【问题描述】:

我正在尝试模拟用户按下 ctrl,当我以编程方式(最初)选择某些内容时,主要目标将是在 datagridview 中,如果不只是添加或减去,我不希望用户更改该选择,就像您要按住 ctrl + 鼠标左键一样。我什至不知道从哪里开始。我试图创建一个与逻辑相结合的选择更改事件,但这将导致无限循环,因为我们将由用户选择一个,然后代码更改其他和其他等无限触发该事件。请帮忙,我对编码有点陌生。我也不知道如何确定 ctrl 键是否已被按下、被按下并被按住。

        private void selecttionh(object sender, EventArgs e)
    {

        if (stage == "4A" || stage == "3B" && ModifierKeys.HasFlag(Keys.Control))
        {
            int nothing = 0;
            btnclickercl bt = new btnclickercl();
            bt.dataGridView1_SelectionChanged(sender, e, dataGridViewReslist, dataGridViewnewres, nothing);
        }
        if (stage == "4A" || stage == "3B" && (ModifierKeys & Keys.Control) != Keys.Control)
        {
            MessageBox.Show("Please Press and hold " + "'ctrl'" + " to continue");
            dataGridViewReslist.ClearSelection();
            for (int i = 0; i < ResRoomSelections.Count; i++)
            {
                dataGridViewReslist.Rows[ResRoomSelections[i][0]].Cells[ResRoomSelections[i][1]].Selected = true;
                dataGridViewReslist.Rows[ResRoomSelections[i][0]].Cells[(ResRoomSelections[i][1]) + 1].Selected = true;
            }
        }
        else
        {
                dataGridViewReslist.ClearSelection();
                for (int i = 0; i < ResRoomSelections.Count; i++)
                {
                    dataGridViewReslist.Rows[ResRoomSelections[i][0]].Cells[ResRoomSelections[i][1]].Selected = true;
                    dataGridViewReslist.Rows[ResRoomSelections[i][0]].Cells[(ResRoomSelections[i][1]) + 1].Selected = true;
                }
        }  

    }

【问题讨论】:

    标签: c# datagridview


    【解决方案1】:

    实现这一点的方法是单独存储选择状态,当用户单击单元格时更新它,然后重新应用它。这可以防止每次单击时选择丢失。如果你钩住了正确的事件处理程序(鼠标,而不是单击),你可以做到这一点,而不会出现屏幕闪烁,否则看起来会一团糟。

    你需要的一切都在这个类中,包括一个扩展方法SetupToggledSelectionMode(),这是你的入口点。

    static public class Example
    {
        static private bool[][] GetSelectionState(DataGridView input)
        {
            int rowCount = input.Rows.Count;
            int columnCount = input.Columns.Count;
            var result = new bool[rowCount][];
            for (var r = 0; r < rowCount; r++)
            {
                result[r] = new bool[columnCount];
                for (var c = 0; c < columnCount; c++)
                {
                    var cell = input.Rows[r].Cells[c];
                    result[r][c] = cell.Selected;
                }
            }
            return result;
        }
    
        static private void SetSelectionState(DataGridView input, bool[][] selectionState)
        {
            for (int r = 0; r <= selectionState.GetUpperBound(0); r++)
            {
                for (int c = 0; c <= selectionState[r].GetUpperBound(0); c++)
                {
                    input.Rows[r].Cells[c].Selected = selectionState[r][c];
                }
            }
        }
    
    
        static public void SetupToggledSelectionMode(this DataGridView input)
        {
            bool[][] selectionState = GetSelectionState(input);  //This will be stored in a closure due to the lambda expressions below
    
            input.CellMouseUp += (object sender, DataGridViewCellMouseEventArgs e) =>
            {
                selectionState[e.RowIndex][e.ColumnIndex] = !selectionState[e.RowIndex][e.ColumnIndex];
                SetSelectionState(input, selectionState);
            };
    
            input.SelectionChanged += (object sender, EventArgs e) =>
            {
                if (selectionState != null)
                {
                    SetSelectionState(input, selectionState);
                }
            };
        }
    }
    

    要使用,填充您的网格视图,以编程方式设置初始选择,然后像这样调用它:

    myDataGrid.DataSource = myData;
    myDataGrid.Refresh();
    myDataGrid.SelectAll();
    myDataGrid.SetupToggledSelectionMode();
    

    SetupToggledSelectionMode() 方法将注册必要的事件处理程序并将网格的选择状态存储在两个处理程序都可以访问的关闭变量中。所以你不必声明任何额外的东西;只需调用方法即可。

    【讨论】:

    • 谢谢你,这对我很有帮助。我所做的只是让它更有效率。因为它会在每一步都调用选择更改,所以我完全摆脱了那个事件,只保留了 CellMouseup 事件。我对这个网站有点陌生,完整的回复如下。
    【解决方案2】:

    谢谢你,这对我很有帮助。我所做的只是让它更有效率。因为它会在每一步都调用选择更改,所以我完全摆脱了那个事件,只保留了 CellMouseup 事件。

    static private bool[][] GetSelectionState(DataGridView input)
    {
        int rowCount = input.Rows.Count;
        int columnCount = input.Columns.Count;
        var result = new List<int[]>();
        for (var r = 0; r < rowCount; r++)
        {
            for (var c = 0; c < columnCount; c++)
            {
                if(input.Rows[r].Cells[c].Selected==true)
               {
                result.add(new int[]{r,c});//will keep only the integer of selected items
               }
            }
        }
        return result;//this for me was a recycled variable it can be used or recycled from somewhere else
    }
    
    private void SetSelectionState(DataGridView input,result)
        {
            for (int i=0;i<result.Count;i++)
            {
                input.Rows[result[i][0]].Cells[result[i][1]].Selected = true;
    
            }
        }
    public void SetupToggledSelectionMode(DataGridView input,result)
        {
         for (int i=0;i<result.Count;i++)
                {
                    if(result[i].SequenceEqual(new int[] { e.RowIndex, e.ColumnIndex }))
                    {
                        result.RemoveAt(i);
                        continueer = 1;
                        break;
                    }
                }
                if (continueer == 0)
                {
                    ResRoomSelections.Add(new int[] { e.RowIndex, e.ColumnIndex });
                }
            SetSelectionState(input);
             //whatever else you need to do 
     }
    

    我知道还有更好的方法来搜索列表,但我无法让 lamda 搜索工作,所以我只是使用了蛮力

    -感谢吴约翰

    【讨论】:

      猜你喜欢
      • 2010-12-23
      • 2012-03-14
      • 1970-01-01
      • 1970-01-01
      • 2013-01-01
      • 2017-11-03
      • 1970-01-01
      • 2013-02-24
      • 2012-09-15
      相关资源
      最近更新 更多