git clone MvvmLight失败,破网络, 就没有直接修改源码的方式来使用了

Nuget安装MvvmLightLibsStd10

使用GalaSoft.MvvmLight.Command命名空间下的RelayCommand会有一个Bug, CanExecute的返回不会更新UI, 在GalaSoft.MvvmLight.CommandWpf中进行了Fixed, 然而MvvmLightLibsStd10并没有GalaSoft.MvvmLight.CommandWpf, 直接粗暴的把GalaSoft.MvvmLight.CommandWpf下面的RelayCommand提到工程中

using GalaSoft.MvvmLight.Helpers;
using System;
using System.Threading;
using System.Windows.Input; namespace TraceApp.LinkLib.Wpf.Extras
{
/// <summary>
/// A command whose sole purpose is to relay its functionality to other
/// objects by invoking delegates. The default return value for the CanExecute
/// method is 'true'. This class does not allow you to accept command parameters in the
/// Execute and CanExecute callback methods.
/// </summary>
/// <remarks>If you are using this class in WPF4.5 or above, you need to use the
/// GalaSoft.MvvmLight.CommandWpf namespace (instead of GalaSoft.MvvmLight.Command).
/// This will enable (or restore) the CommandManager class which handles
/// automatic enabling/disabling of controls based on the CanExecute delegate.</remarks>
public class RelayCommand : ICommand
{
private readonly WeakAction _execute;
private readonly WeakFunc<bool> _canExecute;
private EventHandler _requerySuggestedLocal; /// <summary>
/// Initializes a new instance of the RelayCommand class that
/// can always execute.
/// </summary>
/// <param name="execute">The execution logic. IMPORTANT: If the action causes a closure,
/// you must set keepTargetAlive to true to avoid side effects. </param>
/// <param name="keepTargetAlive">If true, the target of the Action will
/// be kept as a hard reference, which might cause a memory leak. You should only set this
/// parameter to true if the action is causing a closure. See
/// http://galasoft.ch/s/mvvmweakaction. </param>
/// <exception cref="T:System.ArgumentNullException">If the execute argument is null.</exception>
public RelayCommand(Action execute, bool keepTargetAlive = false)
: this(execute, (Func<bool>)null, keepTargetAlive)
{
} /// <summary>Initializes a new instance of the RelayCommand class.</summary>
/// <param name="execute">The execution logic. IMPORTANT: If the action causes a closure,
/// you must set keepTargetAlive to true to avoid side effects. </param>
/// <param name="canExecute">The execution status logic. IMPORTANT: If the func causes a closure,
/// you must set keepTargetAlive to true to avoid side effects. </param>
/// <param name="keepTargetAlive">If true, the target of the Action will
/// be kept as a hard reference, which might cause a memory leak. You should only set this
/// parameter to true if the action is causing a closures. See
/// http://galasoft.ch/s/mvvmweakaction. </param>
/// <exception cref="T:System.ArgumentNullException">If the execute argument is null.</exception>
public RelayCommand(Action execute, Func<bool> canExecute, bool keepTargetAlive = false)
{
if (execute == null)
throw new ArgumentNullException(nameof(execute));
this._execute = new WeakAction(execute, keepTargetAlive);
if (canExecute == null)
return;
this._canExecute = new WeakFunc<bool>(canExecute, keepTargetAlive);
} /// <summary>
/// Occurs when changes occur that affect whether the command should execute.
/// </summary>
public event EventHandler CanExecuteChanged
{
add
{
if (this._canExecute == null)
return;
EventHandler eventHandler = this._requerySuggestedLocal;
EventHandler comparand;
do
{
comparand = eventHandler;
eventHandler = Interlocked.CompareExchange<EventHandler>(ref this._requerySuggestedLocal, comparand + value, comparand);
}
while (eventHandler != comparand);
CommandManager.RequerySuggested += value;
}
remove
{
if (this._canExecute == null)
return;
EventHandler eventHandler = this._requerySuggestedLocal;
EventHandler comparand;
do
{
comparand = eventHandler;
eventHandler = Interlocked.CompareExchange<EventHandler>(ref this._requerySuggestedLocal, comparand - value, comparand);
}
while (eventHandler != comparand);
CommandManager.RequerySuggested -= value;
}
} /// <summary>
/// Raises the <see cref="E:GalaSoft.MvvmLight.CommandWpf.RelayCommand.CanExecuteChanged" /> event.
/// </summary>
public void RaiseCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
} /// <summary>
/// Defines the method that determines whether the command can execute in its current state.
/// </summary>
/// <param name="parameter">This parameter will always be ignored.</param>
/// <returns>true if this command can be executed; otherwise, false.</returns>
public bool CanExecute(object parameter)
{
if (this._canExecute == null)
return true;
if (this._canExecute.IsStatic || this._canExecute.IsAlive)
return this._canExecute.Execute();
return false;
} /// <summary>
/// Defines the method to be called when the command is invoked.
/// </summary>
/// <param name="parameter">This parameter will always be ignored.</param>
public virtual void Execute(object parameter)
{
if (!this.CanExecute(parameter) || this._execute == null || !this._execute.IsStatic && !this._execute.IsAlive)
return;
this._execute.Execute();
}
} /// <summary>
/// A generic command whose sole purpose is to relay its functionality to other
/// objects by invoking delegates. The default return value for the CanExecute
/// method is 'true'. This class allows you to accept command parameters in the
/// Execute and CanExecute callback methods.
/// </summary>
/// <typeparam name="T">The type of the command parameter.</typeparam>
/// <remarks>If you are using this class in WPF4.5 or above, you need to use the
/// GalaSoft.MvvmLight.CommandWpf namespace (instead of GalaSoft.MvvmLight.Command).
/// This will enable (or restore) the CommandManager class which handles
/// automatic enabling/disabling of controls based on the CanExecute delegate.</remarks>
public class RelayCommand<T> : ICommand
{
private readonly WeakAction<T> _execute;
private readonly WeakFunc<T, bool> _canExecute; /// <summary>
/// Initializes a new instance of the RelayCommand class that
/// can always execute.
/// </summary>
/// <param name="execute">The execution logic. IMPORTANT: If the action causes a closure,
/// you must set keepTargetAlive to true to avoid side effects. </param>
/// <param name="keepTargetAlive">If true, the target of the Action will
/// be kept as a hard reference, which might cause a memory leak. You should only set this
/// parameter to true if the action is causing a closure. See
/// http://galasoft.ch/s/mvvmweakaction. </param>
/// <exception cref="T:System.ArgumentNullException">If the execute argument is null.</exception>
public RelayCommand(Action<T> execute, bool keepTargetAlive = false)
: this(execute, (Func<T, bool>)null, keepTargetAlive)
{
} /// <summary>Initializes a new instance of the RelayCommand class.</summary>
/// <param name="execute">The execution logic. IMPORTANT: If the action causes a closure,
/// you must set keepTargetAlive to true to avoid side effects. </param>
/// <param name="canExecute">The execution status logic. IMPORTANT: If the func causes a closure,
/// you must set keepTargetAlive to true to avoid side effects. </param>
/// <param name="keepTargetAlive">If true, the target of the Action will
/// be kept as a hard reference, which might cause a memory leak. You should only set this
/// parameter to true if the action is causing a closure. See
/// http://galasoft.ch/s/mvvmweakaction. </param>
/// <exception cref="T:System.ArgumentNullException">If the execute argument is null.</exception>
public RelayCommand(Action<T> execute, Func<T, bool> canExecute, bool keepTargetAlive = false)
{
if (execute == null)
throw new ArgumentNullException(nameof(execute));
this._execute = new WeakAction<T>(execute, keepTargetAlive);
if (canExecute == null)
return;
this._canExecute = new WeakFunc<T, bool>(canExecute, keepTargetAlive);
} /// <summary>
/// Occurs when changes occur that affect whether the command should execute.
/// </summary>
public event EventHandler CanExecuteChanged
{
add
{
if (this._canExecute == null)
return;
CommandManager.RequerySuggested += value;
}
remove
{
if (this._canExecute == null)
return;
CommandManager.RequerySuggested -= value;
}
} /// <summary>
/// Raises the <see cref="E:GalaSoft.MvvmLight.CommandWpf.RelayCommand`1.CanExecuteChanged" /> event.
/// </summary>
public void RaiseCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
} /// <summary>
/// Defines the method that determines whether the command can execute in its current state.
/// </summary>
/// <param name="parameter">Data used by the command. If the command does not require data
/// to be passed, this object can be set to a null reference</param>
/// <returns>true if this command can be executed; otherwise, false.</returns>
public bool CanExecute(object parameter)
{
if (this._canExecute == null)
return true;
if (this._canExecute.IsStatic || this._canExecute.IsAlive)
{
if (parameter == null && typeof(T).IsValueType)
return this._canExecute.Execute(default(T));
if (parameter == null || parameter is T)
return this._canExecute.Execute((T)parameter);
}
return false;
} /// <summary>
/// Defines the method to be called when the command is invoked.
/// </summary>
/// <param name="parameter">Data used by the command. If the command does not require data
/// to be passed, this object can be set to a null reference</param>
public virtual void Execute(object parameter)
{
object parameter1 = parameter;
if (parameter != null && parameter.GetType() != typeof(T) && parameter is IConvertible)
parameter1 = Convert.ChangeType(parameter, typeof(T), (IFormatProvider)null);
if (!this.CanExecute(parameter1) || this._execute == null || !this._execute.IsStatic && !this._execute.IsAlive)
return;
if (parameter1 == null)
{
if (typeof(T).IsValueType)
this._execute.Execute(default(T));
else
this._execute.Execute(default(T));
}
else
this._execute.Execute((T)parameter1);
}
}
}

一不做二不休, 发现MvvmLightLibsStd10中也没有DispatcherHelper, 也提取出来

using System;
using System.Text;
using System.Windows.Threading; namespace TraceApp.LinkLib.Wpf.Extras
{
/// <summary>
/// Helper class for dispatcher operations on the UI thread.
/// </summary>
public static class DispatcherHelper
{
/// <summary>
/// Gets a reference to the UI thread's dispatcher, after the
/// <see cref="M:GalaSoft.MvvmLight.Threading.DispatcherHelper.Initialize" /> method has been called on the UI thread.
/// </summary>
public static Dispatcher UIDispatcher { get; private set; } /// <summary>
/// Executes an action on the UI thread. If this method is called
/// from the UI thread, the action is executed immendiately. If the
/// method is called from another thread, the action will be enqueued
/// on the UI thread's dispatcher and executed asynchronously.
/// <para>For additional operations on the UI thread, you can get a
/// reference to the UI thread's dispatcher thanks to the property
/// <see cref="P:GalaSoft.MvvmLight.Threading.DispatcherHelper.UIDispatcher" /></para>.
/// </summary>
/// <param name="action">The action that will be executed on the UI
/// thread.</param>
public static void CheckBeginInvokeOnUI(Action action)
{
if (action == null)
return;
DispatcherHelper.CheckDispatcher();
if (DispatcherHelper.UIDispatcher.CheckAccess())
action();
else
DispatcherHelper.UIDispatcher.BeginInvoke((Delegate)action);
} private static void CheckDispatcher()
{
if (DispatcherHelper.UIDispatcher == null)
{
StringBuilder stringBuilder = new StringBuilder("The DispatcherHelper is not initialized.");
stringBuilder.AppendLine();
stringBuilder.Append("Call DispatcherHelper.Initialize() in the static App constructor.");
throw new InvalidOperationException(stringBuilder.ToString());
}
} /// <summary>Invokes an action asynchronously on the UI thread.</summary>
/// <param name="action">The action that must be executed.</param>
/// <returns>An object, which is returned immediately after BeginInvoke is called, that can be used to interact
/// with the delegate as it is pending execution in the event queue.</returns>
public static DispatcherOperation RunAsync(Action action)
{
DispatcherHelper.CheckDispatcher();
return DispatcherHelper.UIDispatcher.BeginInvoke((Delegate)action);
} /// <summary>
/// This method should be called once on the UI thread to ensure that
/// the <see cref="P:GalaSoft.MvvmLight.Threading.DispatcherHelper.UIDispatcher" /> property is initialized.
/// <para>In a Silverlight application, call this method in the
/// Application_Startup event handler, after the MainPage is constructed.</para>
/// <para>In WPF, call this method on the static App() constructor.</para>
/// </summary>
public static void Initialize()
{
if (DispatcherHelper.UIDispatcher != null && DispatcherHelper.UIDispatcher.Thread.IsAlive)
return;
DispatcherHelper.UIDispatcher = Dispatcher.CurrentDispatcher;
} /// <summary>
/// Resets the class by deleting the <see cref="P:GalaSoft.MvvmLight.Threading.DispatcherHelper.UIDispatcher" />
/// </summary>
public static void Reset()
{
DispatcherHelper.UIDispatcher = (Dispatcher)null;
}
}
}
Nuget安装Microsoft.Extensions.DependencyInjection
创建一个类AppLocator, 在App.Xaml中申明为全局资源来做Service的注册来View的绑定

AppLocator

using System;
using System.IO;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Trace.Model;
using TraceApp.DB;
using TraceApp.ViewModel; namespace TraceApp
{
public class AppLocator
{
public IServiceProvider ServiceProvider { get; private set; }
public IConfiguration Configuration { get; private set; } public AppLocator()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", true, true);
Configuration = builder.Build(); var collection = new ServiceCollection();
ConfigureServices(collection);
ServiceProvider = collection.BuildServiceProvider();
} private void ConfigureServices(IServiceCollection services)
{
// Configuration
services.Configure<AppSettings>(Configuration.GetSection(nameof(AppSettings)));
// Database
services.AddDbContext<MyContext>(options =>
{
options.UseSqlite("Data Source=TraceApp.db3");
options.UseLoggerFactory(LoggerFactory.Create(builder =>
{
builder.AddFilter((category, level) =>
category == DbLoggerCategory.Database.Command.Name
&& level == LogLevel.Information);
builder.AddConsole();
}));
}); #region Register ViewModel
services.AddSingleton<MainWindowViewModel>();
#endregion
} #region ViewModel's DataContexts
public MainWindowViewModel MainWindow => ServiceProvider.GetService<MainWindowViewModel>();
#endregion
}
}
运行, 效果是自己想要的

附上App.Xaml、MainWindow.Xaml、MainWindowViewModel.cs的代码

App.Xaml

<Application  x:Class="TraceApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TraceApp">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!--Handy Control-->
<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml"/>
<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml"/>
</ResourceDictionary.MergedDictionaries>
<local:AppLocator x:Key="AppLocator"/>
</ResourceDictionary>
</Application.Resources>
</Application>

MainWindow.Xaml

<Window x:Class="TraceApp.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
DataContext="{Binding Source={StaticResource AppLocator}, Path=MainWindow}"
Title="MainWindow" d:DesignHeight="500" d:DesignWidth="800">
<Grid>
<WrapPanel>
<TextBlock Text="{Binding Title}"/>
<Button Content="测试命令" Command="{Binding TestCommand}"/>
<CheckBox IsChecked="{Binding Enable, Mode=TwoWay}"/>
</WrapPanel>
</Grid>
</Window>

MainWindowViewModel

using GalaSoft.MvvmLight;
using HandyControl.Controls;
using TraceApp.LinkLib.Wpf.Extras; namespace TraceApp.ViewModel
{
public class MainWindowViewModel : ViewModelBase
{
private string _title = "Wpf Mvvm Application";
public string Title
{
get => _title;
set => Set(ref _title, value);
} private bool _enable = false;
public bool Enable { get => _enable; set => Set(ref _enable, value); } public RelayCommand TestCommand => new RelayCommand(() => { MessageBox.Show("Test!"); },
() => Enable); public MainWindowViewModel()
{ }
}
}
没有了Nuget安装MvvmLight在.NetCore中使用的Warnning, 强迫症的心情愉快了很多

MvvmLight + Microsoft.Extensions.DependencyInjection + WpfApp(.NetCore3.1)的更多相关文章

  1. DotNetCore跨平台~一起聊聊Microsoft.Extensions.DependencyInjection

    写这篇文章的心情:激动 Microsoft.Extensions.DependencyInjection在github上同样是开源的,它在dotnetcore里被广泛的使用,比起之前的autofac, ...

  2. 解析 Microsoft.Extensions.DependencyInjection 2.x 版本实现

    项目使用了 Microsoft.Extensions.DependencyInjection 2.x 版本,遇到第2次请求时非常高的内存占用情况,于是作了调查,本文对 3.0 版本仍然适用. 先说结论 ...

  3. 使用诊断工具观察 Microsoft.Extensions.DependencyInjection 2.x 版本的内存占用

    目录 准备工作 大量接口与实现类的生成 elasticsearch+kibana+apm asp.net core 应用 请求与快照 Kibana 上的请求记录 请求耗时的分析 请求内存的分析 第2次 ...

  4. Microsoft.Extensions.DependencyInjection 之三:展开测试

    目录 前文回顾 IServiceCallSite CallSiteFactory ServiceProviderEngine CompiledServiceProviderEngine Dynamic ...

  5. Microsoft.Extensions.DependencyInjection 之三:反射可以一战(附源代码)

    目录 前文回顾 IServiceCallSite CallSiteFactory ServiceProviderEngine CompiledServiceProviderEngine Dynamic ...

  6. Microsoft.Extensions.DependencyInjection 之二:使用诊断工具观察内存占用

    目录 准备工作 大量接口与实现类的生成 elasticsearch+kibana+apm asp.net core 应用 请求与快照 Kibana 上的请求记录 请求耗时的分析 请求内存的分析 第2次 ...

  7. Microsoft.Extensions.DependencyInjection 之一:解析实现

    [TOC] 前言 项目使用了 Microsoft.Extensions.DependencyInjection 2.x 版本,遇到第2次请求时非常高的内存占用情况,于是作了调查,本文对 3.0 版本仍 ...

  8. 使用 Microsoft.Extensions.DependencyInjection 进行依赖注入

    没有 Autofac DryIoc Grace LightInject Lamar Stashbox Unity Ninject 的日子,才是好日子~~~~~~~~~~ Using .NET Core ...

  9. Microsoft.Extensions.DependencyInjection中的Transient依赖注入关系,使用不当会造成内存泄漏

    Microsoft.Extensions.DependencyInjection中(下面简称DI)的Transient依赖注入关系,表示每次DI获取一个全新的注入对象.但是使用Transient依赖注 ...

随机推荐

  1. P5520 【[yLOI2019] 青原樱】

    P5520 [[yLOI2019] 青原樱]题解 整理博客的时候改了下分类标签,重新审一下 题目传送门 翻了翻题解区,发现基本没和我写的一样的(主要是都比我的写的简单 看题目: 第一眼,数学题:第二眼 ...

  2. Python (深浅拷贝)

    1.深拷贝  -->  克隆一份,修改拷贝后的内容不对原对象内容产生影响 拷贝后修改序列中元素内容,注意:被修改的元素不能为一个序列中的某个值 a = [["北京多测师",& ...

  3. sequel pro无法连接mysql服务器

    1. 添加用户 GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'your_passwd' WITH GRANT OPTION; FLU ...

  4. Java集合面试题汇总篇

    文章收录在 GitHub JavaKeeper ,N线互联网开发必备技能兵器谱 作为一位小菜 "一面面试官",面试过程中,我肯定会问 Java 集合的内容,同时作为求职者,也肯定会 ...

  5. Spring官网阅读(十八)Spring中的AOP

    文章目录 什么是AOP AOP中的核心概念 切面 连接点 通知 切点 引入 目标对象 代理对象 织入 Spring中如何使用AOP 1.开启AOP 2.申明切面 3.申明切点 切点表达式 excecu ...

  6. matlab读取csv文件并显示

    传统的方式可以通过读取文件,然后处理字符串的方式对csv文件进行解析,在matlab中可以通过csvread函数读取csv文件,然后通过plot对数据进行显示,也可以对里面的函数进行分析: csv文件 ...

  7. STM32 TIM 编码器模式采集编码器信号

    layout: post tags: [STM32] comments: true 文章目录 @[toc] 什么是正交解码? 编码器接口模式 标准库接口 TIM_TimeBaseInitTypeDef ...

  8. FPGA自计数六位共阳极数码管动态显示2(调用task的方法)

    `timescale 1ns/1ps module adc_dis( clk , rst_n , sm_seg , sm_bit ); input clk;//50HZ input rst_n; :] ...

  9. [hdu5445 Food Problem]多重背包

    题意:一堆食物,有价值.空间.数量三种属性,一些卡车,有空间,价格,数量三种属性.求最少的钱(不超过50000)买卡车装下价值大于等于给定价值的食物,食物可以拆开来放. 思路:这题的关键是给定的条件: ...

  10. 开发一个maven脚手架

    写在前面 开发新项目就需要搭建新工程,但是搭建新工程的这个过程是非常繁琐浪费时间的,并且不可避免的需要踩坑.更可怕的是,如果是在一个团队中,每新起一个项目都由不同的开发人员去自定义的搭建工程结构,那么 ...