C# with WPF 笔记1 时间: 2019-08-02 00:01 分类: 技术笔记 > 简单记录下C# WPF开发的一些技巧和踩过的坑 ## 1.Window ###1.图标 Icon属性 `Icon="Properties/bitbug_favicon.ico"`来加载放到Properties里的图标 ###2.仅最小化 `ResizeMode="CanMinimize"` ##2.Textbox ###1.设置选中 `TxtInAddr.Focus();` ###2.只读 `IsReadOnly="True"` ###3.横向自动滚动到后面 ```C# TxtOutAddr.CaretIndex = TxtOutAddr.Text.Length; var rect = TxtOutAddr.GetRectFromCharacterIndex(TxtOutAddr.CaretIndex); TxtOutAddr.ScrollToHorizontalOffset(rect.Right);``` ###4.防止文本框换行 用Grid.Row的Height。Wrap设置默认就是不换行 ###5.附加文本 ```C# TxtShell.AppendText(e.Data); TxtShell.AppendText("\n"); //因为不自动换行 ``` ###6.纵向自动滚屏到最新行 ```C# private void TxtShell_TextChanged(object sender, EventArgs e) { TxtShell.SelectionStart = TxtShell.Text.Length; //Set the current caret position at the end TxtShell.ScrollToEnd(); //Now scroll it automatically } ``` 别忘了顺便给Wrap自动换行和Verticle滚轮打开。 另外注意上面第二个参数的类型 ##3.格式化字符串 ```C# String.Format("\"{0}\" --list-subs{1} --no-check-certificate", TxtInAddr.Text, proxy_builder())``` ##4.MessageBox ```C# System.Windows.Forms.MessageBox.Show(String.Format("请检查{0}是否存在!", program), "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); ``` ##5.实现运行shell程序且将结果实时刷新到textbox上且运行完成后自动解锁按钮 ###1.运行Shell ```C# public void RunShell(object sender, EventArgs e) { Console.WriteLine(String.Format("{0} {1}", this.FileName, this.Arguments)); TxtShell.AppendText("\n"); try { System.Diagnostics.Process p = new System.Diagnostics.Process(); p.StartInfo.FileName = this.FileName; p.StartInfo.Arguments = this.Arguments; p.StartInfo.UseShellExecute = false; //是否使用操作系统shell启动 p.StartInfo.RedirectStandardInput = true;//接受来自调用程序的输入信息 p.StartInfo.RedirectStandardOutput = true;//由调用程序获取输出信息 p.StartInfo.RedirectStandardError = true;//重定向标准错误输出 p.StartInfo.CreateNoWindow = true;//不显示程序窗口 //p.StandardInput.WriteLine("exit"); p.EnableRaisingEvents = true; p.OutputDataReceived += flushShellTxt; p.ErrorDataReceived += flushShellTxt; p.Exited += FinishProcess; p.Start();//启动程序 p.BeginOutputReadLine(); p.BeginErrorReadLine(); // p.StandardInput.AutoFlush = true; //TxtShell.Text = output; } catch (System.ComponentModel.Win32Exception) { throw new Exception("Error occurred when running command."); } } ``` 实时更新的核心是 ```C# p.EnableRaisingEvents = true; p.OutputDataReceived += flushShellTxt; p.ErrorDataReceived += flushShellTxt; ``` 以下必须放在`P.Start()`之前否则无法刷新 程序还会卡住一直到执行完毕。其中`flushShellTxt`为更新textbox的函数,后面会讲。 实现运行后解锁按钮的核心是`p.Exited += FinishProcess;`同理`FinishProcess`也是解锁按钮的函数。 ###2.更新Textbox ```C# private void flushShellTxt(object sender, DataReceivedEventArgs e) { Action action1 = () => { TxtShell.AppendText(e.Data); TxtShell.AppendText("\n"); }; TxtShell.Dispatcher.BeginInvoke(action1); } ``` 由于WPF和Shell是不同的进程,想要访问界面元件必须采用上述方式,将修改元件的函数丢到`.Dispatcher.BeginInvoke`方法指定的`Action`“匿名函数”一类的东西里。 ###3.解锁button 同理, 但注意第二个参数类型是`EventArgs`和上面的不一样。 ```C# private void FinishProcess(object sender, EventArgs e) { Action action1 = () => { okButton.IsEnabled = true; }; okButton.Dispatcher.BeginInvoke(action1); } ``` ##6.检测Shell运行的程序是否存在 ```C# public static bool ExistsOnPath(string exeName) { try { using (Process p = new Process()) { p.StartInfo.UseShellExecute = false; p.StartInfo.FileName = "where"; p.StartInfo.Arguments = exeName; p.StartInfo.CreateNoWindow = true; p.Start(); p.WaitForExit(); return p.ExitCode == 0; } } catch (Win32Exception) { throw new Exception("'where' command is not on path"); } } ``` 采用Where命令最为简单粗暴 但仅用于Win(大概)。 标签: C# WPF