WPF开发问题点与解决方法记录
1. WPF DataGrid 右键聚焦当前行问题。
原因分析:左键聚焦,右键调取菜单,因为菜单分为行菜单与整张表格菜单,导致右键常常无法准确聚焦某一行。
方法:添加LoadingRow事件,在加载行时为每行添加右键事件,该事件的实现内容时Focus().
//页面后台文件中添加
private void dg_LoadingRow(object sender, DataGridRowEventArgs e)
{
e.Row.MouseRightButtonDown += (s, a) =>
{
a.Handled = true;
(sender as DataGrid).SelectedIndex = (s as DataGridRow).GetIndex();
(s as DataGridRow).Focus();
};
}
//前段页面添加事件
<DataGrid
...
LoadingRow="dataGridMotionList_LoadingRow">
2. While循环一直调用,导致cpu占用过高。
原因分析:无论是UI线程还是临时子线程,在执行耗时代码时,若没有请求CPU分配时间片,Cpu会将全部或者大部分的资源都耗在该线程中直到线程退出。
方法:在耗时线程中添加Thread.Sleep(1); 便能将Cpu使用率降到10%以下
while(true){
Thread.Sleep(1);//通知cpu分配时间片
//你的代码
}
3.弹出窗口执行Close()时关闭不干净,二次Show的时候报异常:无法再次显示未关闭的对话框。
分析原因:调用this.close() 不能完整得关闭窗口,因为窗口已经注册过,需要进系统窗口将其删除,或杀死该APP进程(Application.Current.Shutdown();)。
方法:将窗体不用的时候隐藏起来,一般弹出框只是显示功能并不太占资源。
/// <summary>
/// 重写OnClosing事件 解决窗口关闭不能再开的bug。
/// </summary>
/// <param name="e"></param>
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
this.Hide();
//窗体内容清空
}
6.自定义命令绑定
WPF提供很多窗体所需的命令,只需要做简单绑定就能使用,比如:
<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.Open" Executed="OpenCommand_Executed"/>
</Window.CommandBindings>
........
<MenuItem Header="载入(用例或配置)" Command="Open">
而有些特殊按钮希望通过命令触发而不是Click事件的则需要自定义命令并绑定。
自定义命令要求所有定义以及事件处理调用都为静态,所以如果实在窗体类中定义命令时,需要再创建静态构造方法来定义 如:
private static RoutedUICommand autoMove;
static MainWindow()
{
InputGestureCollection inputs = new InputGestureCollection();
inputs.Add(new KeyGesture(Key.A, ModifierKeys.Control, "A"));
autoMove = new RoutedUICommand("aa", "ff", typeof(MainWindow), inputs);
CommandManager.RegisterClassCommandBinding(typeof(MainWindow), new CommandBinding(autoMove, CommandBinding_Executed));
}
定义内容里前两句是为该命令创建快捷键输入触发,如不需要可忽略。第三句是命令定义实体,此次定义的是RoutedUICommand,它是RoutedCommand的一个分支,参数按需传递。注意new的时候前两个字符串为空会报异常。第三个参数的Type表示命令作用画面的类型。 最后一句就是绑定了,首先说明该绑定的作用类,然后创建绑定,将命令与执行方法绑在一起,该执行方法即命令触发事件。
使用时需指明路径:
xmlns:local="clr-namespace:XXXXXX"
Command="local:MainWindow.AutoMove" //这是所有涉及的方法与属性必须静态的原因。
有时为了统一,也可以将绑定语句写在Xaml里如
<Window.CommandBindings>
<CommandBinding Command="local:MainWindow.AutoMove" Executed="CommandBinding_Executed"/>
</Window.CommandBindings>
使用方法同上。
WPF界面优化记录
1.将子窗体显示在父窗体任意位置。
方法:
WindowStartupLocation="Manual" 表示位置可变
在show之前设置
_Instance.Owner = owner as System.Windows.Window;
_Instance.Top = _Instance.Owner.Top + _Instance.Owner.Height/1.1;
_Instance.Left = _Instance.Owner.Left + _Instance.Owner.Width/2;
其中,可重写Show代码或者其他方法,将该子窗体的父窗体对象传进来,然后基于父窗体设置该窗体的相对位置。
2.自定义窗体拖动栏(实现与Windows下相似的功能)
分析原因:win7自带的窗体边框样式单一不方便修改重写,所以并将其弃用,自建边框,但原本该有的关闭 放大 缩小 拖动等功能是必要的。
方法:
[1]删除原有的边框
WindowStyle="None" //必要
AllowsTransparency="True" //必要
Background="Transparent"
[2]将窗体分成上下两个Row,在Row0的地方建一个布局,当做窗体的拖动栏。在其上添加右键按下事件MouseLeftButtonDown,事件内容为this.DragMove();
[3]在Row0的布局里添加标题、菜单、和按钮,实现放大隐藏和关闭功能,分别是
放大: this.Height = SystemParameters.WorkArea.Height;
this.Width = SystemParameters.WorkArea.Width;
this.Top = 0;
this.Left = 0;
隐藏:this.WindowState = WindowState.Minimized;
关闭:如果是主窗体,Application.Current.Shutdown(); 否则调用this.Close().
1. WPF DataGrid 右键聚焦当前行问题。
原因分析:左键聚焦,右键调取菜单,因为菜单分为行菜单与整张表格菜单,导致右键常常无法准确聚焦某一行。
方法:添加LoadingRow事件,在加载行时为每行添加右键事件,该事件的实现内容时Focus().
//页面后台文件中添加
private void dg_LoadingRow(object sender, DataGridRowEventArgs e)
{
e.Row.MouseRightButtonDown += (s, a) =>
{
a.Handled = true;
(sender as DataGrid).SelectedIndex = (s as DataGridRow).GetIndex();
(s as DataGridRow).Focus();
};
}
//前段页面添加事件
<DataGrid
...
LoadingRow="dataGridMotionList_LoadingRow">
2. While循环一直调用,导致cpu占用过高。
原因分析:无论是UI线程还是临时子线程,在执行耗时代码时,若没有请求CPU分配时间片,Cpu会将全部或者大部分的资源都耗在该线程中直到线程退出。
方法:在耗时线程中添加Thread.Sleep(1); 便能将Cpu使用率降到10%以下
while(true){
Thread.Sleep(1);//通知cpu分配时间片
//你的代码
}
3.弹出窗口执行Close()时关闭不干净,二次Show的时候报异常:无法再次显示未关闭的对话框。
分析原因:调用this.close() 不能完整得关闭窗口,因为窗口已经注册过,需要进系统窗口将其删除,或杀死该APP进程(Application.Current.Shutdown();)。
方法:将窗体不用的时候隐藏起来,一般弹出框只是显示功能并不太占资源。
/// <summary>
/// 重写OnClosing事件 解决窗口关闭不能再开的bug。
/// </summary>
/// <param name="e"></param>
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
this.Hide();
//窗体内容清空
}
6.自定义命令绑定
WPF提供很多窗体所需的命令,只需要做简单绑定就能使用,比如:
<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.Open" Executed="OpenCommand_Executed"/>
</Window.CommandBindings>
........
<MenuItem Header="载入(用例或配置)" Command="Open">
而有些特殊按钮希望通过命令触发而不是Click事件的则需要自定义命令并绑定。
自定义命令要求所有定义以及事件处理调用都为静态,所以如果实在窗体类中定义命令时,需要再创建静态构造方法来定义 如:
private static RoutedUICommand autoMove;
static MainWindow()
{
InputGestureCollection inputs = new InputGestureCollection();
inputs.Add(new KeyGesture(Key.A, ModifierKeys.Control, "A"));
autoMove = new RoutedUICommand("aa", "ff", typeof(MainWindow), inputs);
CommandManager.RegisterClassCommandBinding(typeof(MainWindow), new CommandBinding(autoMove, CommandBinding_Executed));
}
定义内容里前两句是为该命令创建快捷键输入触发,如不需要可忽略。第三句是命令定义实体,此次定义的是RoutedUICommand,它是RoutedCommand的一个分支,参数按需传递。注意new的时候前两个字符串为空会报异常。第三个参数的Type表示命令作用画面的类型。 最后一句就是绑定了,首先说明该绑定的作用类,然后创建绑定,将命令与执行方法绑在一起,该执行方法即命令触发事件。
使用时需指明路径:
xmlns:local="clr-namespace:XXXXXX"
Command="local:MainWindow.AutoMove" //这是所有涉及的方法与属性必须静态的原因。
有时为了统一,也可以将绑定语句写在Xaml里如
<Window.CommandBindings>
<CommandBinding Command="local:MainWindow.AutoMove" Executed="CommandBinding_Executed"/>
</Window.CommandBindings>
使用方法同上。
WPF界面优化记录
1.将子窗体显示在父窗体任意位置。
方法:
WindowStartupLocation="Manual" 表示位置可变
在show之前设置
_Instance.Owner = owner as System.Windows.Window;
_Instance.Top = _Instance.Owner.Top + _Instance.Owner.Height/1.1;
_Instance.Left = _Instance.Owner.Left + _Instance.Owner.Width/2;
其中,可重写Show代码或者其他方法,将该子窗体的父窗体对象传进来,然后基于父窗体设置该窗体的相对位置。
2.自定义窗体拖动栏(实现与Windows下相似的功能)
分析原因:win7自带的窗体边框样式单一不方便修改重写,所以并将其弃用,自建边框,但原本该有的关闭 放大 缩小 拖动等功能是必要的。
方法:
[1]删除原有的边框
WindowStyle="None" //必要
AllowsTransparency="True" //必要
Background="Transparent"
[2]将窗体分成上下两个Row,在Row0的地方建一个布局,当做窗体的拖动栏。在其上添加右键按下事件MouseLeftButtonDown,事件内容为this.DragMove();
[3]在Row0的布局里添加标题、菜单、和按钮,实现放大隐藏和关闭功能,分别是
放大: this.Height = SystemParameters.WorkArea.Height;
this.Width = SystemParameters.WorkArea.Width;
this.Top = 0;
this.Left = 0;
隐藏:this.WindowState = WindowState.Minimized;
关闭:如果是主窗体,Application.Current.Shutdown(); 否则调用this.Close().