【C#】winform中 遇到的一些问题

        以往都是做的网站接口什么的,比较少接触桌面软件,刚好最近抽空用了winform做一个桌面软件玩玩,使用 SunnyUI 类库 做界面,遇到一些问题,在此做个记录。

 1. DateGridView 添加按钮

 winform原生控件不美观,用了SunnyUI,就比较好看了,不过SunnyUI需要授权才能解锁更多功能,对于开源版的,有些功能就得自己实现了。

 DateGridView 是个 常见的 控件,一般用来做表格,就像网站的一些列表,最后一列 是操作列, 做一些 按钮 等功能,比如 编辑,删除,预览 。使用DateGridView直接来做按钮就比较麻烦,虽然也 有提供单元格可以设置 为 按钮 的 功能,但是 对于样式 就不好修改了,而且一列多个按钮就比较 麻烦了,最终还是得自己实现了(参考了网上一些思路),自个渲染按钮了。

//获取按钮控件(这里做了一些简单的封装,方便统一按钮样式,写死只弄了3种颜色)
private UIButton GetBtnByType(string strBtnName, string strBtnText,
int tag, EventHandler handler = null, int ButtonColor = 0)
        {
            var btn = new UIButton();
            btn.Name = strBtnName;
            btn.Text = strBtnText;
            btn.Tag = tag;
            btn.BackColor = Color.White;
            btn.FillColor = Color.White;
            btn.FillHoverColor = Color.White;
            btn.FillPressColor = Color.White;
            btn.RectColor = Color.White;
            btn.RectHoverColor = Color.White;
            btn.RectPressColor = Color.White;

            if (ButtonColor == 1)
            {
                btn.ForeColor = Color.FromArgb(233, 70, 108);
                btn.ForeHoverColor = Color.OrangeRed;
                btn.ForePressColor = Color.OrangeRed;
            }
            else if (ButtonColor == 2)
            {
                btn.ForeColor = Color.LightSkyBlue;
                btn.ForeHoverColor = Color.Blue;
                btn.ForePressColor = Color.Blue;
            }
            else
            {
                btn.ForeColor = Color.FromArgb(66, 66, 66);
                btn.ForeHoverColor = Color.LightSkyBlue;
                btn.ForePressColor = Color.LightSkyBlue;
            }
            if (handler != null)
            {
                btn.Click += handler;
            }
            return btn;
        }
//这个是 userList,即DateGridView 循环显示数据 时候,在对应行 添加 按钮
//userList 需要把 控件 添加 进来
//i是 第几行,cloum 是 第几列,num 是 把单元格宽度平分(几个按钮就平分几个,根据需要)
//Size 和 Location 也根据需要了
//mButtons 是 保存 添加 到 DateGridView 里 的 按钮
//为了控制这些按钮的 隐藏和现实等,我这里只弄了 2个按钮,第二个传空,代表没有按钮

var btnEdit = GetBtnByType("name_" + i, "查看", i, button_Clikc,2);
this.userList.Controls.Add(btnEdit);
Rectangle rectangle = this.userList.GetCellDisplayRectangle(cloum, i, true);
btnEdit.Size = new Size(rectangle.Width / num - 2, rectangle.Height-2);
btnEdit.Location = new Point(rectangle.Left+1, rectangle.Top+1);
mButtons.Add(new ActionButtons(btnEdit,null));
//保存 每一行 操作列 的 按钮 对象, 这里 只弄了 两个 按钮(其实可以弄成更灵活的,这里就偷懒了)
//这个 也是参考 网上 改来的
internal class ActionButtons
    {
        public ActionButtons(UIButton addButton, UIButton removeButton)
        {
            AddButton = addButton;
            RemoveButton = removeButton;
            if (AddButton!=null)
            {
                num++;
            }
            if (RemoveButton != null)
            {
                num++;
            }
        }
        public int num { get; set; }=0;
        public UIButton AddButton { get; set; }
        public UIButton RemoveButton { get; set; }
    }

只做到 这一步 ,按钮 基本上 就 可以 显示 出来了, 也可以绑定事件。但是 对于 行 的 数量 过多的,会出现 一种情况,就是  滚动面板的 时候 ,按钮 不会 动,被固定了,所以 还得 对 DateGridView 的 滚动  事件 绑定 更新按钮 位置 的 功能。

 //隐藏按钮
private void HideAllActionButtons(ActionButtons ab)
{
     if (ab.AddButton != null)
     {
         ab.AddButton.Visible = false;
     }
     if (ab.RemoveButton != null)
     {
         ab.RemoveButton.Visible = false;
     }
}

//更新按钮位置
private void UpdateActionButtonsPosition(ActionButtons ab, Rectangle rect, int rowIndex)
{
      if (ab.AddButton!=null)
      {
          ab.AddButton.Location = new Point(rect.Left+2, rect.Top+2);
          ab.AddButton.Size = new Size(rect.Width / ab.num - 4, rect.Height-4);
          ab.AddButton.Visible = true;
      }
      if (ab.RemoveButton != null)
      {
         ab.RemoveButton.Location = new Point(ab.AddButton.Width + rect.Left+ 2, rect.Top+2);
          ab.RemoveButton.Size = ab.AddButton.Size;
          ab.RemoveButton.Visible = true;// rowIndex > 0;
      }
}
//重新定位按钮位置
//Sleep 不加的话 有点问题 (不记得啥问题了)
//先 拿到 面板 显示 的 起始行 和 面板 能显示 的 行数量
//得出 起始 和 结束 行数(这些 就是 需要显示的,其他的按钮 要隐藏)
//因为是在非主线程中操作,所以需要委托主线程来执行操作控件
private void RepositionActionButtons(List<ActionButtons> mButtons,UIDataGridView dgvList,int colum)
{
     Task.Run(() =>
     {
         Thread.Sleep(50);
         int firstRow = dgvList.FirstDisplayedScrollingRowIndex;
         int lastRow = firstRow + dgvList.DisplayedRowCount(false);

         for (int i = 0; i < mButtons.Count; i++)
         {
              ActionButtons ab = mButtons[i];
              if (i >= firstRow && i <= lastRow)
              {
                 Rectangle rect = dgvList.GetCellDisplayRectangle(colum, i, false);
                 userList.Invoke((Action)(() =>
                 {
                     UpdateActionButtonsPosition(ab, rect, i);
                 }));
              }else
              {
                 userList.Invoke((Action)(() =>
                 {
                     HideAllActionButtons(ab);
                 }));
              }
          }
        });
}

//绑定 滚动事件
//cloum 是 第几列
private void dataGridView1_Scroll(object sender, ScrollEventArgs e)
{
      var dgv= sender as UIDataGridView;
      var i = dgv.Tag.ToInt(); //可以根据 i 来决定 操作 哪个 表格 和 哪些按钮,可复用的写法
      var cloum=4;
      RepositionActionButtons(mButtons,userList,cloum);        
}
//每次刷新数据 需要重新绑定按钮,所以要清理掉
//但是 有BUG的样子,Controls.Clear() 一次请不干净,所以得循环了
for (var i = 0; i < 10; i++)
{
    userList.Controls.Clear();
}

这样基本上就完成了  DateGridView 添加 按钮了,样式就需要自己慢慢调整了。

2.由于需求,需要实现列的拖拽功能(就是列手动换位置),发现 winform 的gdv本身有自带了

AllowUserToOrderColumns 设置为 true 即可

监听对应事件是这个:  ColumnDisplayIndexChanged

做个记录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沃祐进先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值