我遇到的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 - 影天 - 博客园

相关文章
相关标签/搜索