我遇到的WPF的坑

轉自 林德熙Bloghtml

本文:我遇到的WPF的坑git

目錄github

  1. 單例應用在多實例用戶沒法使用
  2. 標記方法被使用
  3. 當鼠標滑過一個被禁用的元素時,讓ToolTip 顯示
  4. 獲取設備屏幕數量
  5. 獲取當前域用戶
  6. 綁定資源文件裏面的資源
  7. 判斷 WPF 程序使用管理員權限運行
  8. 註冊全局事件
  9. 高版本的 WPF 引用低版本類庫致使沒法啓動
  10. 非託管使用託管委託
  11. 元素失去得到
  12. 反射引用程序集
  13. 使用十進制設置顏色
  14. WPF 判斷文件是否隱藏
  15. 觸發鼠標事件
  16. TextBlock 換行
  17. 在 xaml 綁定索引空格
  18. 使用 Task ContinueWith 在主線程
  19. WPF-數據綁定:日期時間格式
  20. WPF 第三方DLL 強簽名
  21. WPF 去掉最大化按鈕
  22. WPF TextBox 全選
  23. WPF 獲取文本光標寬度

單例應用在多實例用戶沒法使用

若是使用NamedPipeServerStream、Mutex作單實例,須要傳入字符串,這時若是傳入一個固定的字符串,會在多用戶的時候沒法使用。c#

由於若是在一個用戶啓動的軟件,那麼就註冊了這個字符串,在另外一個用戶就沒法啓動。解決方法是傳入Environment.UserNamewindows

在構造函數傳入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)
    {
        //被引用
    }
}

當鼠標滑過一個被禁用的元素時,讓ToolTip 顯示

設置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 就能夠

判斷 WPF 程序使用管理員權限運行

引用命名空間,複製下面代碼,而後調用 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(方法));

高版本的 WPF 引用低版本類庫致使沒法啓動

若是在一個 .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 判斷文件是否隱藏

能夠設置一些文件是隱藏文件,那麼 WPF 如何判斷 FileInfo 是隱藏文件?

簡單的代碼,經過判斷 Attributes 就能夠獲得,請看下面。

file.Attributes.HasFlag(FileAttributes.Hidden)

觸發鼠標事件

觸發鼠標點下事件,可使用下面代碼

element.RaiseEvent(new MouseEventArgs(Mouse.PrimaryDevice, 1)
            {
                RoutedEvent = Mouse.MouseDownEvent
            });

TextBlock 換行

使用 &#10; 就能夠換行

win10 uwp 在 xaml 讓 TextBlock 換行

在 xaml 綁定索引空格

若是一個索引須要傳入空格,那麼在 xaml 使用下面代碼是沒法綁定

{Binding MyCollection[foo bar]}

須要使用下面代碼

{Binding MyCollection[[foo&x20;bar]]}

Binding to an index with space in XAML – Ivan Krivyakov

使用 Task ContinueWith 在主線程

在有時候使用 Task 的 Delay 以後想要返回主線程,可使用 ContinueWith 的方法,請看代碼

Task.Delay(TimeSpan.FromSeconds(5)).ContinueWith
            (
                _ => Foo()
                // 若是 Foo 不須要在主線程,請註釋下面一段代碼
                , TaskScheduler.FromCurrentSynchronizationContext()
            );

核心是 TaskScheduler.FromCurrentSynchronizationContext 方法

若是 Foo 不須要在主線程,就能夠刪除 TaskScheduler.FromCurrentSynchronizationContext 代碼

WPF-數據綁定:日期時間格式

{Binding datetime,StringFormat='{}{0:yyyy年MM月dd日 dddd HH:mm:ss}',ConverterCulture=zh-CN}

指定ConverterCulture爲zh-CN後星期就顯示爲中文了。

WPF 第三方DLL 強簽名

參見:http://www.cnblogs.com/xjt927/p/5317678.html

WPF 去掉最大化按鈕

經過在窗口添加下面代碼

ResizeMode="NoResize"

窗口就剩下一個關閉同時用戶也沒法拖動修改窗口大小

WPF TextBox 全選

在一個按鈕點擊的時候全選 TextBox 的內容,能夠在按鈕裏面調用 SelectAll 方法

textBox.SelectAll();

上面代碼的 textBox 就是界面寫的 TextBox 元素

若是發現調用上面的代碼 TextBox 沒有全選,多是 TextBox 沒有拿到焦點,能夠嘗試下面代碼

textBox.Focus();
textBox.SelectAll();

WPF 獲取文本光標寬度

經過 SystemParameters.CaretWidth 獲取寬度

var caretWidth = SystemParameters.CaretWidth;

詳細請看 SystemParameters.CaretWidth Property

wpf動畫——new PropertyPath屬性鏈 - 影天 - 博客園

wpf動畫——緩動動畫Animation Easing - 影天 - 博客園

相關文章
相關標籤/搜索