轉自 林德熙Bloghtml
本文:我遇到的WPF的坑git
目錄github
若是使用NamedPipeServerStream、Mutex
作單實例,須要傳入字符串,這時若是傳入一個固定的字符串,會在多用戶的時候沒法使用。c#
由於若是在一個用戶啓動的軟件,那麼就註冊了這個字符串,在另外一個用戶就沒法啓動。解決方法是傳入Environment.UserName
。windows
在構造函數傳入Environment.UserName
有關的字符串就能夠在一個用戶進行單例,其餘用戶打開是本身的軟件。api
public partial class App { #region Constants and Fields /// <summary>The event mutex name.</summary> private const string UniqueEventName = "{GUID}"; /// <summary>The unique mutex name.</summary> private const string UniqueMutexName = "{GUID}"; //這裏須要加 Environment.UserName /// <summary>The event wait handle.</summary> private EventWaitHandle eventWaitHandle; /// <summary>The mutex.</summary> private Mutex mutex; #endregion #region Methods /// <summary>The app on startup.</summary> /// <param name="sender">The sender.</param> /// <param name="e">The e.</param> private void AppOnStartup(object sender, StartupEventArgs e) { bool isOwned; this.mutex = new Mutex(true, UniqueMutexName, out isOwned); this.eventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset, UniqueEventName); // So, R# would not give a warning that this variable is not used. GC.KeepAlive(this.mutex); if (isOwned) { // Spawn a thread which will be waiting for our event var thread = new Thread( () => { while (this.eventWaitHandle.WaitOne()) { Current.Dispatcher.BeginInvoke( (Action)(() => ((MainWindow)Current.MainWindow).BringToForeground())); } }); // It is important mark it as background otherwise it will prevent app from exiting. thread.IsBackground = true; thread.Start(); return; } // Notify other instance so it could bring itself to foreground. this.eventWaitHandle.Set(); // Terminate this instance. this.Shutdown(); } #endregion }
使用 UsedImplicitly 特性能夠標記一個沒有被引用的方法爲反射使用,這時就不會被優化刪除。app
public class Foo { [UsedImplicitly] public Foo() { //反射調用 } public Foo(string str) { //被引用 } }
設置ToolTipService.ShowOnDisabled
爲 true函數
<Button ToolTipService.ShowOnDisabled="True">
經過 WinForms 方法獲取post
System.Windows.Forms.Screen.AllScreens
上面就能夠拿到全部的屏幕,經過 Count 方法就能夠知道有多少屏幕優化
var screenCount = Screen.AllScreens.Length;
在 WPF 找到當前登錄的用戶使用下面代碼
using System.Security.Principal; // 其餘代碼 WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent(); string crentUserAd = windowsIdentity.Name;
輸出 crentUserAd
能夠看到 設備\\用戶
的格式
在 WPF 的 xaml 能夠經過 x:Static
綁定資源,可是要求資源文件裏面的對應資源設置訪問爲公開
若是沒有設置那麼將會在 xaml 運行的時候提示
System.Windows.Markup.XamlParseException 在 System.Windows.Markup.StaticExtension 上提供值xxx
此時在設計器裏面是能夠看到綁定成功,只是在運行的時候提示找不到,展開能夠看到下面提示
沒法將 xx.Properties.Resources.xx StaticExtension 值解析爲枚舉、靜態字段或靜態屬性
解決方法是在 Resource.resx 裏面的訪問權限從 internal 修改成 public 就能夠
引用命名空間,複製下面代碼,而後調用 IsAdministrator 方法,若是返回 true 就是使用管理員權限運行
using System.Security.Principal; public static bool IsAdministrator() { WindowsIdentity current = WindowsIdentity.GetCurrent(); WindowsPrincipal windowsPrincipal = new WindowsPrincipal(current); //WindowsBuiltInRole能夠枚舉出不少權限,例如系統用戶、User、Guest等等 return windowsPrincipal.IsInRole(WindowsBuiltInRole.Administrator); }
C# 判斷軟件是不是管理員權限運行 - 除卻猩猩不是猿 - CSDN博客
若是須要註冊一個類型的全局事件,如拿到 TextBox 的全局輸入,那麼可使用下面代碼
EventManager.RegisterClassHandler(typeof(TextBox), TextBox.KeyDownEvent, new RoutedEventHandler(方法));
若是在一個 .net 4.0 的 WPF 程序引用一個 .net 2.0 的庫,那麼就會讓程序沒法運行,解決方法添加useLegacyV2RuntimeActivationPolicy
打開 app.config 添加 useLegacyV2RuntimeActivationPolicy="true"
在 startup 元素
下面是 app.config 代碼
<?xml version="1.0" encoding="utf-8"?> <configuration> <startup useLegacyV2RuntimeActivationPolicy="true"> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/> </startup> </configuration>
參見:WPF 軟件引用其餘類庫啓動無反應問題 - 灰色年華 - CSDN博客
若是有一個 C++ 寫的dll,他須要一個函數指針,在C#使用,就能夠傳入委託。
那麼簡單的方法是這樣寫:
private static void Func(){} public void C() { c(Func); }
其中c就是C++寫的函數,傳進去看起來好像正常。
可是有時候程序不知道怎麼就炸了。
由於這樣寫是不對的。
傳入的不是函數地址,傳入的是把函數隱式轉換委託,而後轉換的委託是局部變量,會被gc,因此在C++拿到的是一個被回收的委託,調用時就會炸。
這裏沒法用catch,因此用這個會讓程序退出。
調用C#的函數,使用委託,是隱式轉換,上面代碼能夠寫成下面的
private static void Func(){} public void C() { var temp = new delegate(){ Func }; c(temp); }
因而在函數完就把temp放到gc在調用時找不到委託。
一個好的作法
private static void Func(){} private delegate Temp { get; } = new delegate(){Func}; private void C() { c(Temp); }
放在靜態變量不會gc調用不會空,能夠這樣不會出現上面問題。
元素可使用 CaptureMouse 方法得到,這能夠用在拖動,一旦拖動出元素能夠得到,獲得拖動結束。
可是有時會失去得到,若是本身須要失去,可使用 Mouse.Capture(null) 可是在沒有本身使用的這個函數,失去得到,能夠的是:
設置元素可命中false,若是看到元素失去交互,並且堆棧沒有任何地方使用失去得到,那麼可能就是存在設置元素可命中false。
若是有兩個函數同時 得到 一個元素,會不會出現 失去得到?不會,若是同一個元素屢次 得到,那麼不會出現失去得到。若是這是讓另外一個得到,那麼這個元素就是失去得到。能夠經過元素.IsMouseCaptured 判斷元素得到。
能夠經過 Mouse.Captured 得到如今 Mouse 是否得到。若是返回是 null ,沒有得到,可是元素得到存在一些問題,在失去焦點或其餘,可能就失去得到。
CaptureMouse/CaptureStylus 可能會失敗 - walterlv
這是比較難以說明的問題,總之,可能出現的問題就是引用了一個 xaml 使用的資源庫,或使用了一個只有反射才訪問的庫。
緣由: 若是在引用一個庫,引用代碼沒有直接使用的程序集。使用的方法就是使用 xaml 或反射來使用。那麼在生成,vs 不會把程序集放在輸出文件夾。
問題: 反射報錯,沒法找到程序集。
例子: 若是我用了一個程序集,然而代碼沒有直接引用,而是反射使用,這樣,vs判斷這個程序集沒有使用,最後把他清除。因此會出現反射沒法拿到,並且很難知道這裏出現坑。
爲了解決 xaml 和反射沒法拿到的坑,可使用 在任意位置使用 Debug.Write(typeof(程序集裏的一個類)) 方法讓 vs 引用程序集。
那麼在 Release 上爲什麼還能夠把程序集放在輸出文件夾呢?由於我也不知道緣由,若是你知道的話,那麼請告訴我一下。
在 xaml 若是須要使用 十進制設置顏色,請使用下面代碼
<SolidColorBrush x:Key="LikeGreen"> <SolidColorBrush.Color> <Color R="100" G="200" B="30" A="100"/> </SolidColorBrush.Color> </SolidColorBrush>
https://stackoverflow.com/a/47952098/6116637
能夠設置一些文件是隱藏文件,那麼 WPF 如何判斷 FileInfo 是隱藏文件?
簡單的代碼,經過判斷 Attributes 就能夠獲得,請看下面。
file.Attributes.HasFlag(FileAttributes.Hidden)
觸發鼠標點下事件,可使用下面代碼
element.RaiseEvent(new MouseEventArgs(Mouse.PrimaryDevice, 1) { RoutedEvent = Mouse.MouseDownEvent });
使用
就能夠換行
win10 uwp 在 xaml 讓 TextBlock 換行
若是一個索引須要傳入空格,那麼在 xaml 使用下面代碼是沒法綁定
{Binding MyCollection[foo bar]}
須要使用下面代碼
{Binding MyCollection[[foo&x20;bar]]}
Binding to an index with space in XAML – Ivan Krivyakov
在有時候使用 Task 的 Delay 以後想要返回主線程,可使用 ContinueWith 的方法,請看代碼
Task.Delay(TimeSpan.FromSeconds(5)).ContinueWith ( _ => Foo() // 若是 Foo 不須要在主線程,請註釋下面一段代碼 , TaskScheduler.FromCurrentSynchronizationContext() );
核心是 TaskScheduler.FromCurrentSynchronizationContext 方法
若是 Foo 不須要在主線程,就能夠刪除 TaskScheduler.FromCurrentSynchronizationContext 代碼
{Binding datetime,StringFormat='{}{0:yyyy年MM月dd日 dddd HH:mm:ss}',ConverterCulture=zh-CN}
指定ConverterCulture爲zh-CN後星期就顯示爲中文了。
參見:http://www.cnblogs.com/xjt927/p/5317678.html
經過在窗口添加下面代碼
ResizeMode="NoResize"
窗口就剩下一個關閉同時用戶也沒法拖動修改窗口大小
在一個按鈕點擊的時候全選 TextBox 的內容,能夠在按鈕裏面調用 SelectAll 方法
textBox.SelectAll();
上面代碼的 textBox 就是界面寫的 TextBox 元素
若是發現調用上面的代碼 TextBox 沒有全選,多是 TextBox 沒有拿到焦點,能夠嘗試下面代碼
textBox.Focus(); textBox.SelectAll();
經過 SystemParameters.CaretWidth
獲取寬度
var caretWidth = SystemParameters.CaretWidth;
詳細請看 SystemParameters.CaretWidth Property