Winform:timer tick事件无法触发
情况描述
在其他的控件、对象事件中启用timer.Enable=true,但是事件触发了以后timer无法触发进入timer的tick事件中
原因分析
该控件、对象事件的进程在结束后,该事件进程销毁,同时timer开启的事件也会销毁,从而无法进入到timer的tick事件中。
解决办法
使用线程的方法来解决,重新开一个线程来执行timer控件的延时,可以使用委托方法进行解决。
/// 同步委托
this.Invoke(new MethodInvoker(delegate
{
timer1.Interval = 500;
timer1.Start();
}));
///异步委托
this.BeginInvoke(new MethodInvoker(delegate
{
timer1.Interval = Convert.ToInt32(CBox_Timer_Interval1.Text);//转换straing类型为int类型
//timer1.Interval = 200;
timer1.Start();
}));
建议用异步委托的方法,如果这里采用同步委托的话,会造成委托的timer事件会抢占主线程事件,阻塞线程
WPF:调用线程无法访问此对象
情况描述
WPF多线程程序运行调试时报错:调用线程无法访问此对象,因为另一个线程拥有该对象
原因分析
解决办法
1.BeginInvoke()异步执行,不等待委托结束就更新;
2.Invoke()同步执行,需等待委托执行完。
YourControl.Dispatcher.BeginInvoke(new Action(delegate
{
//Do sth with Your Control
}));
YourControl.Dispatcher.Invoke(new Action(delegate
{
//Do sth with Your Control
}));
WPF:不支持从调度程序线程以外的线程对其 SourceCollection 进行的更改
情况描述
报错信息:System.NotSupportedException:“该类型的 CollectionView 不支持从调度程序线程以外的线程对其 SourceCollection 进行的更改。
原因分析
问题在WPF中的VM类中ObservableCollection类型,该类型的 CollectionView 不支持从调度程序线程以外的线程对其 SourceCollection 进行的更改
解决办法
ThreadPool.QueueUserWorkItem(delegate
{
SynchronizationContext.SetSynchronizationContext(new DispatcherSynchronizationContext(Application.Current.Dispatcher));
SynchronizationContext.Current.Post(pl =>
{
//here write what you want to do
//onlineHosts.Add(new HostInfo() { id = client.ID, ip = client.IP, isOnline = true });
}, null);
});
WPF:Binding 判断值处理
需求描述
DataGrid、ListView等控件中某一个列绑定的是一个bool型的类成员,需要根据这个bool型的 true/false 显示 是/否等处理后的值
解决办法
三种方法:
1、传统的Binding方法,后台构造好数据,绑定就行。
2、转换器方法(Converter),绑定后,触发转换器,转换器负责把值转换成需要的内容。
3、DataTrigger方法,直接在xaml里面对数据进行处理,展示所需要的内容。
原解决方式页面不可访问,以第三种为例实现成功,代码如下:
<GridViewColumn Width="90" Header="状态">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock>
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=isOnline}" Value="False">
<Setter Property="Text" Value="离线" />
<Setter Property="Foreground" Value="Red" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=isOnline}" Value="True">
<Setter Property="Text" Value="在线" />
<Setter Property="Foreground" Value="Green" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
根据绑定的isOnline值触发显示效果,如果为true,显示绿色字体的“在线”,false显示红色字体的“离线”
WPF:获取Label控件的Width问题
情况描述
如果Label控件未设定指定宽度,在程序中读取Label控件的宽度时,无论是label.Width,还是label.ActualWidth均存在问题(Width为NaN,ActualWidth不等于实际控件宽度
原因分析
Width:是我们期望控件应有的宽度,是可读写的,可在xaml文件中设置,也可在程序中设置。如果没有设置,Width的值为NaN(Not a Number)
ActualWidth:是控件Render的实际宽度,控件Render之前,它的值为0,。该属性是只读的。
Render相关内容没有了解的很详细,还没搞清楚这个的具体原因。
解决办法
lblMsg.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
Size s = lblMsg.DesiredSize;
MessageBox.Show($"label的宽度为{s.Width}");
WPF:SqlSugar UNIQUE constraint failed错误
情况描述
在使用SqlSugar进行sqlite数据库插入操作时,发生异常报错,错误内容为 UNIQUE constraint failed错误
原因分析
可能发生这种BUG的两种情况:
1:定义的字段为NOT NULL,而插入时对应的字段为NULL
2:定义的字段为PRIMARY,而插入时想插入的值已经在表中存在。
我的程序执行插入操作时未指定id值(已设定为自增),以为SqlSugar会自动插入,但是实际上没有,因为数据库表的实体类未指定NOT NULL 和PRIMARY 属性
解决办法
//using SqlSugar;
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
public int id { get; set; }
WPF:解决Stream Writer中文乱码问题
情况描述
使用Stream Writer写文件时,路径出现中文会乱码,使用new StreamWriter (path,Encoding.UTF8)同样不起作用
解决办法
在工具栏》NuGet包管理器》管理解决方案的NuGet程序包中,搜索 System.Text.Encoding.CodePages并安装,使用以下代码调用即可
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
StreamReader sr = new StreamReader(fs, Encoding.GetEncoding("GB2312"));