【C#】可以点击单行文本的Popup控件
零 需求分析
小芬在公司有很多活,忙的时候堆了一堆需求,这几天空闲了一点,就开始解决陈年需求,不留着过年了。记得半年前有同事说,希望BugFree的客户端可以做到点击bug悬浮窗时,自动进入bug详情网页。
现有的BugFree客户端是这样的:登录后,显示小小的彩色悬浮按钮组,鼠标悬浮在按钮上时,显示对应的bug信息。这是用ToolTip做的,所以鼠标移出按钮范围后,弹窗会关闭。所有的bug信息是同一个Label元件的Content属性。
那么为了解决同事的需求,我们需要:
1. 鼠标移开悬浮按钮后,bug信息保持若干秒
2. bug信息分解成多个Label或TextBox控件(这里用了TextBox,因为Label的Content属性不能赋值)
3. 给每个TextBox控件添加一个MouseLeftDown之类的点击事件,触发时用Process.Start(url)打开url
4. 给每个TextBox控件添加与url的映射关系
上代码
1. TextViewModel.js
这里定义了一个TexViewModel类,用于DataContext的动态绑定。其中list1和list2都是用于绑定的数据源,可以自行添加ObservableCollection<string>对象,实现更多组数据的绑定。
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms.VisualStyles;
namespace NameSpace1
{
public class TextViewModel : INotifyPropertyChanged
{
public ObservableCollection<string> list1 { get; set; }
public ObservableCollection<string> list2 { get; set; }
public Dictionary<string,int> infoIDDic { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public TextViewModel()
{
list1= new ObservableCollection<string>();
lsit2 = new ObservableCollection<string>();
}
public void Push1(string s,int i)
{
list1.Add(s);
infoIDDic[s] = i;
}
public void Push2(string s,int i)
{
list2.Add(s);
infoIDDic[s]= i;
}
public void Clear()
{
list1.Clear();
list2.Clear();
infoIDDic.Clear();
}
}
}
2. Form1.xaml
这里声明了适用于整个Window文件的DataContext,定义了一个Popup控件,把它的数据绑定到DataContext
<Window x:Name="window" x:Class="NameSpace1.Form1"
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:NameSpace1"
mc:Ignorable="d"
Title="程序0.0" Height="42" Width="102" Background="Transparent" WindowStyle="None" AllowsTransparency="True" ShowInTaskbar="False" Topmost="True" ResizeMode="NoResize" WindowStartupLocation="Manual" Icon="/BugFreeEx;component/images/Logo.ico" ShowActivated="False">
<Window.DataContext>
<local:TextViewModel/>
</Window.DataContext>
<Grid>
<Polygon x:Name="p_1" Points="0,0 50,0 50,20 0,20" Fill="Red" Cursor="Hand" />
<TextBlock x:Name="tb_Active" TextAlignment="Center" Width="50" Height="20" Margin="0,0,50,20" IsHitTestVisible="False" />
<Popup x:Name="activePopup" AllowsTransparency="True" StaysOpen="False" Placement="Mouse" PopupAnimation="Fade">
<Border BorderBrush="Black" BorderThickness="1" Background="White" Padding="5">
<ItemsControl ItemsSource="{Binding list1}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" Margin="5" MouseDown="Label_MouseLeftButtonDown"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
</Popup>
3. Form1.xaml.cs
这里没有给出Bugs添加元素的代码,请读者自行完成。
private void init()
{
activePopup.MouseLeftButtonDown += this.Window_MouseLeftButtonDown;
activePopup.MouseEnter += MouseEnter_Polygon;
activePopup.MouseUp += MouseDown_Polygon;
Bugs = new TextViewModel();
DataContext = Bugs;
}
private void MouseEnter_Polygon(object sender, MouseEventArgs e)
{
activePopup.IsOpen = true;//鼠标进入按钮时,显示Popup控件
}
private void MouseDown_Polygon(object sender, MouseEventArgs e)
{
activePopup.IsOpen = false;//鼠标点击按钮时,隐藏Popup控件
}
private void Label_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
TextBlock textBlock = sender as TextBlock;
if (textBlock!= null)
{
string s = textBlock.Text;
int id = Bugs.infoIDDic[s];
if (id == 0)
{
return;
}
System.Diagnostics.Process.Start(url+id.ToString());
}
}