C#如何解决房态图mouseLeave事件与mouseDown的冲突

antique_star 2017-03-04 08:46:51
各位C#大伽:

本人用动态Button在容器flowlayoutpanel中实现房态图效果如下:


以下是鼠标按下的效果:


现在问题来了:当按下指定房号按钮后,鼠标离开会触发离开事件。所以我就在MouseDown事件中关闭Leave事件,并且判断之前有无按钮被按下,如果有,那么先恢复之前按钮的相应事件,再处理本身按钮的事件。代码如下:

private void Bt_MouseEnter(object sender, EventArgs e)//房态按钮鼠标进入事件
{
Button bt2 = (Button)sender;
bt2.FlatAppearance.BorderSize = 3;
bt2.FlatAppearance.BorderColor = System.Drawing.Color.GreenYellow;
}

private void Bt_MouseLeave(object sender, EventArgs e)//房态按钮鼠标离开事件
{
Button bt3 = (Button)sender;
bt3.FlatAppearance.BorderSize = 0;
}

private void Bt_MouseDown(object sender, EventArgs e)//房态按钮鼠标按下事件
{
Button bt4 = (Button)sender;
if (ClickRoomNo != null)
{
foreach (Control c in flowLayoutPanel1.Controls)//先处理上一个控件,恢复它的两个事件
{
if (c.Text == ClickRoomNo)
{
c.MouseLeave += new EventHandler(Bt_MouseEnter);
c.MouseLeave += new EventHandler(Bt_MouseLeave);
c.FlatAppearance.BorderSize = 3;//此处报错,没有这个属性,可是C就是代表Button啊!百思不得其解
break;
}
}

ClickRoomNo = bt4.Text;
bt4.FlatAppearance.BorderSize = 3;
bt4.FlatAppearance.BorderColor = System.Drawing.Color.Black;
bt4.MouseLeave -= new EventHandler(Bt_MouseLeave);
bt4.MouseLeave -= new EventHandler(Bt_MouseEnter);
}
else
{
ClickRoomNo = bt4.Text;
bt4.FlatAppearance.BorderSize = 3;
bt4.FlatAppearance.BorderColor = System.Drawing.Color.Black;
bt4.MouseLeave -= new EventHandler(Bt_MouseLeave);
bt4.MouseLeave -= new EventHandler(Bt_MouseEnter);
}
}

上面的ClickRoomNo是一个存储按下按钮对应的房号,即动态Button的Text属性。
但实际运行中效果却不尽如人意。当第二次按下按钮时,


好了,说了这么多。直入正题:
1、Down事件中,Control C 如何设置它的FlatAppearance.BorderSize和FlatAppearance.BorderColor属性?
本人是新手,的确有点无法理解。

2、要实现用户下一次点击各房号按钮之前,一直保持被选定状态,如何优化我的代码?

3、还有一个鼠标指针离开FlowLayoutPanel容器去点击文件菜单或功能按钮,比如:在某个房号被按下时,再点击功能按钮【登记入住】,此时打开入住登记子窗体,子窗体要捕获用户选的是哪个房间,该怎么写?关键点语句就行,不用写全,我每个房间按钮的唯一属性就是Button的Text属性【房号】。

拜托大神了。我之前是搞VBA,凭着一股蛮劲切入了C#,并且不是系统地学习,而是由需求向上倒逼自己去研究。所以很小白,很外行。甚至连SQL都是临时UI层面需要用到时,利用静态数据去模拟实际效果。当然我知道这一路会很艰苦,但我相信,只要有兴趣,一切都不是问题。希望大神们提携一下我。
...全文
328 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
antique_star 2017-03-05
  • 打赏
  • 举报
回复
非常感谢大家的及时帮助,每一个人的话里都或多或少让我受益匪浅。 昨晚我彻底给自己放了个假,想着一早起来,能有人帮我解惑。 没想到真的回复这么及时,这是我在本论坛发的第一个求助贴。 最后还要特别特别地跟5楼大侠说一声:谢谢。 你的回复在我结完贴后才刷新出来,抱歉,没法给你分了,要不然我一定给你最多的分。 因为你的回复才是最实在的实战经验,这个思维模式的转变会让我少走很多弯路。 另外,我最近两个月来的C#学习过程,基本全靠百度, 而您的头像尤为熟悉,我的很多基础关键知识都是从您那学习来的, 不是博客就是你在帮别人解答时的回复里, 反正,经常能搜到您的头像。 再次说声:谢谢您啦!
  • 打赏
  • 举报
回复
对于
            var bt3 = (房间)sender;
            if(!bt3.是否选定)
                ..............
这类代码,成文自明,因为代码就是业务逻辑,因为代码借助“用户控件”这个设计模式而封装到了跟系统业务分析文档完全一致的程度了,你所针对的控件就是“房态控件”而不是什么低级的“Button控件”。 而满脑子只有 Button 控件的方式,虽然在理解业务需求时很高大上,但是一写代码就发现“按钮并没有‘是否选定’的属性”,所以就弄出一大堆零散的数据和逻辑来了。这样写代码就跟业务很容易脱节了,很容易写乱了。
  • 打赏
  • 举报
回复
经常有人纠结于“用什么控件”的问题,其实详细设计(注意是说的“设计”而非实现)时是要落实到控件层面,但是也要考虑封装的层次,不是说零零碎碎地去纠结一大堆内容,而要适当地面向对象进行抽象。而用户控件就是一个最基本的 UI 抽象、模块化机制。 对于这个窗口设计,你不能把“房间”作为一个用户控件模块而独立出去设计开发,这其实就反而增加了编程复杂性。所有那些认为“越是底层的控件越方便、越‘快’、越省力”的说法,适合一开始编写简单的课堂练习。而项目设计中,应该提高抽象封装层次,才能更简单地重构更清晰的程序逻辑,少写代码。
  • 打赏
  • 举报
回复
不要过分进行事件修改动作,这容易混乱,因为你的修改是“入侵式”的,而不是响应式的。应该在视图状态中来记录“选定”状态,然后仅仅依据状态来编程。 例如(这里假设你使用名为“房间”的一个“用户控件来封装了单独某个房间的房态界面)
    public partial class 房间 : UserControl
    {
        public 房间()
        {
            InitializeComponent();
        }

        public string 房间号
        {
            get
            {
                  .................
            }
            set
            {
                  .................
            }
        }

        public bool 是否选定
        {
            get
            {
                  .................
            }
            set
            {
                  .................
            }
        }

........
那么你的 MouseLeave可以在时间处理中按照业务规则来设计界面表现,也就是类似
private void 房间_MouseLeave(object sender, EventArgs e)//房态按钮鼠标离开事件
        {
            var bt3 = (房间)sender;
            if(!bt3.是否选定)
            {
                bt3.TheButton.FlatAppearance.BorderSize = 0;  //用户控件暴露一个Button 类型的 TheButton 属性
            }
        }
而另一个 MouseDown 事件处理方法中,并不应该去胡乱改动事件绑定,应该是去设置“房间控件”的“是否选定”属性。 总结一下,就是,你编程设计时应该提高一层次的设计,不要心中只有一大堆底层的 Button 控件,而要将“房间”局部界面的完整业务信息、操作方法,封装到用户控件中,作为一个整体来使用。这样你在设计流程时,就很自然地更多地考虑方便地结合业务逻辑了,“当房间是选中状态时,MouseLeave 就不应该再另外设置细边框”。当你描述界面用户体验时很方便地使用业务术语,而不是满脑子纠结于底层控件,编程也就简单了。 而这就在于你能够在组合 UI 控件时就将界面封装的层次提高一层,使用用户控件来封装“房态”对象,而不是用什么 Button 控件。
xuzuning 2017-03-05
  • 打赏
  • 举报
回复
FlatAppearance 是 Button 的专有属性 考虑到 flowLayoutPanel1 中只有 Button foreach (Control c in flowLayoutPanel1.Controls) 写成这样较好 foreach (Button c in flowLayoutPanel1.Controls) 其实这个用自定义控件比较好(鼠标事件都封装在里面)
xuggzu 2017-03-04
  • 打赏
  • 举报
回复
补充:如果项目时间充足,学下wpf吧,你要的效果对它是轻而易举的。
xuggzu 2017-03-04
  • 打赏
  • 举报
回复
建议:如果需要同时标识多个房间操作状态,可以考虑用tooglebutton组件,比你这个模拟边框效果更直观,事件也不用处理那么复杂。如果同时只能有一个房间了操作,考虑用radiobutton(外观可以变成方形),此时,很多你现在要处理的模拟效果代码根本不用写
a312637477 2017-03-04
  • 打赏
  • 举报
回复
c.FlatAppearance.BorderSize = 3;//此处报错,没有这个属性,可是C就是代表Button啊!百思不得其解 Button tmpBtn=(Button)c; tmpBtn.FlatAppearance.BorderSize=3;

110,561

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧