MinimalisticWPF 2.9.0

dotnet add package MinimalisticWPF --version 2.9.0                
NuGet\Install-Package MinimalisticWPF -Version 2.9.0                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="MinimalisticWPF" Version="2.9.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add MinimalisticWPF --version 2.9.0                
#r "nuget: MinimalisticWPF, 2.9.0"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install MinimalisticWPF as a Cake Addin
#addin nuget:?package=MinimalisticWPF&version=2.9.0

// Install MinimalisticWPF as a Cake Tool
#tool nuget:?package=MinimalisticWPF&version=2.9.0                

MinimalisticWPF

UserControl and Animation are the most important parts in WPF project. This library will allow you to speed up these parts by using C# & Source Generator.

Get →

Practice →


Features


Transition

namespace

  using MinimalisticWPF.TransitionSystem;

(1)Quick

Load the transition on the instance by using the extension method

  var control = new Grid();
  control.Transition()
      .SetProperty(x=>x.Background,Brushes.Red)
      .SetParams((p) =>
      {
          p.Duration = 3;
          p.IsAutoReverse = true;
          p.LoopTime = 2;
      })
      .Start();

(2)Reusable

The transition is described beforehand and then applied for multiple instances

  var control1 = new Grid();
  var control2 = new Grid();
  var transition = Transition.Create<Grid>()
      .SetProperty(x=>x.Background,Brushes.Red)
      .SetParams((p) =>
      {
          p.Duration = 3;
          p.IsAutoReverse = true;
          p.LoopTime = 2;
      });
  control1.BeginTransition(transition);
  control2.BeginTransition(transition);

(3)Shared

Running multiple transitions, some shared mechanism makes them thread-safe

  • Share a transition parameter
  • A transition can either be terminated manually or a new transition can be started to override the current one
  • Can use the methods provided by Transition to terminate the transition
  var control = new Grid();

  var param = new TransitionParams()
  {
      Duration = 3,
      IsAutoReverse = true,
      LoopTime = 2,
  };
  var transition1 = Transition.Create<Grid>()
      .SetProperty(x => x.Background, Brushes.Red)
      .SetParams(param);
  var transition2 = Transition.Create<Grid>()
      .SetProperty(x => x.Width, 100)
      .SetParams(param);

  var transition = Transition.Create([transition1, transition2]);

  control.BeginTransition(transition);

  // Transition.DisposeAll();
  // Transition.Dispose(control);

(4)Isolation

Running multiple transitions, some isolation mechanism can make the effect more flexible, but it is not thread-safe

  • Each transition must contain explicit effect parameters in advance
  • Transitions in progress can only be terminated manually
  • Can use the scheduler to terminate the transition
  var control = new Grid();

  var param1 = new TransitionParams()
  {
      Duration = 3,
      IsAutoReverse = true,
  };
  var param2 = new TransitionParams()
  {
      Duration = 1,
      LoopTime = 15
  };
  var transition1 = Transition.Create<Grid>()
      .SetProperty(x => x.Background, Brushes.Red)
      .SetParams(param1);
  var transition2 = Transition.Create<Grid>()
      .SetProperty(x => x.Width, 100)
      .SetProperty(x => x.Height, 100)
      .SetParams(param2);

  var schedulers = control.BeginTransitions(transition1, transition2);

  // schedulers[0].Dispose();
  // schedulers[1].Dispose();

(5)Compile

You can make the transition immutable with the Compile operation

  var control1 = new Grid();
  var control2 = new Grid();

  var param = new TransitionParams()
  {
      Duration = 3,
      IsAutoReverse = true,
      LoopTime = 2,
  };
  var transition1 = Transition.Create<Grid>()
      .SetProperty(x => x.Background, Brushes.Red)
      .SetParams(param);
  var transition2 = Transition.Create<Grid>()
      .SetProperty(x => x.Width, 100)
      .SetParams(param);

  var transition = Transition.Create([transition1, transition2]);
  var compile = Transition.Compile([transition1, transition2], param, null);

  param.LoopTime = 10;

  control1.BeginTransition(transition);
  control2.BeginTransition(compile);

ViewModel

This is the heart of the library. You will build awesome user controls in Mvvm mode using clean C# code

★ Ultimately, everything is abstracted to data, and changing the data changes the functionality, and all you need in XAML is data binding !

(1)Field

Automatically generate properties for fields

  [Observable]
  private int _id = 0;
  partial void OnIdChanged(int oldValue, int newValue)
  {
      
  }
  partial void OnIdChanging(int oldValue, int newValue)
  {
      
  }

(2)Constructor

Multiple constructors are generated automatically.Functions with the same parameter list will be called from within the same constructor

  [Constructor]
  private void SetDefaultValue()
  {

  }

  [Constructor]
  private void SetDefaultValues(int id, int age)
  {

  }

(3)Hover

Controls need to animate in response to your mouse hovering over them

  [Observable(CanHover: true)]
  private Brush background = Brushes.White;

  [Constructor]
  private void SetDefaultValue()
  {
      // The default values are the same as the initial values of the fields, and you can change the values of these properties to achieve the mouse hover animation
      HoveredBackground = Brushes.Cyan;
      NoHoveredBackground = Brushes.White;

      // You can change the transition details
      HoveredTransition.SetParams(TransitionParams.Hover);
      NoHoveredTransition.SetParams(TransitionParams.Hover);

      // This change will automatically enable the hover transition
      IsHovered = true;

      // You can see if the hover transition is loading
      if (IsHoverChanging)
      {

      }
  }

(4)Theme

Easily realize light and dark theme switch or other custom theme

  [Observable]
  [Dark("#1e1e1e")]
  [Light("White")]
  private Brush background = Brushes.White;

  [Constructor]
  private void SetDefaultTheme()
  {
      // Setting the current theme
      CurrentTheme = typeof(Light);

      // You can see if you're switching topics
      if (IsThemeChanging)
      {

      }
  }

  partial void OnThemeChanging(Type? oldTheme, Type newTheme)
  {
      
  }
  partial void OnThemeChanged(Type? oldTheme, Type newTheme)
  {
      
  }

(5)Dependency

You can easily make user controls have dependency properties with the same name as properties in the ViewModel

  • param1 → DataContext type name
  • param2 → The name of the namespace in which the ViewModel is defined. If no class with the same name exists, omit namespace validation
  [DataContextConfig(nameof(Class1), "TestForMWpf")]
  public partial class MainWindow : Window
  • Class1
    public partial class Class1
    {
        [Observable(CanDependency:true)]
        [Dark("#1e1e1e")]
        [Light("White")]
        private Brush background = Brushes.White;
    }
  • Once configured, the control already contains dependency properties with the same name as properties in the ViewModel.

Here are some options

  partial void OnBackgroundChanged(Brush oldValue, Brush newValue)
  {
      
  }
  partial void OnDarkBackgroundChanged(Brush oldValue, Brush newValue)
  {
      
  }
  partial void OnLightBackgroundChanged(Brush oldValue, Brush newValue)
  {
      
  }

AOP

Allows you to dynamically override, extend, and intercept methods without modifying the source code of a class

  • Mark properties, methods
    internal partial class Class1
    {
        [AspectOriented]
        public string Property { get; set; } = string.Empty;

        [AspectOriented]
        public void Action()
        {

        }
    }
  • Set up custom logic
    • Method parameters
      • first → Before the method is called
      • second → Original logic, passing null means no coverage
      • third → After the method is called
    • Delegate parameters
      • para → The arguments received when the method is called
      • last → The return value of the previous step
  var c1 = new Class1();

  c1.Proxy.SetMethod(nameof(c1.Action),
      (para, last) => { MessageBox.Show("Intercept method"); return null; },
      null,
      null);
  c1.Proxy.SetPropertyGetter(nameof(c1.Property),
      (para, last) => { MessageBox.Show("Intercept getter"); return null; },
      null,
      null);
  c1.Proxy.SetPropertySetter(nameof(c1.Property),
      (para, last) => { MessageBox.Show("Intercept setter"); return null; },
      null,
      null);

  c1.Proxy.Action();
  var a = c1.Proxy.Property;
  // Members are accessed through Proxy

ObjectPool

In the implementation of some visual effects, using object pooling makes it easier to avoid performance issues

    [ObjectPool]
    internal partial class Class2
    {
        public Class2()
        {
            Pool.Record(this);
        }

        private double _counter = 0;
        public double Counter
        {
            get => _counter;
            set
            {
                _counter = value;
                if (CanRelease())
                {
                    Pool.Release(this);
                }
            }
        }

        private bool _isfinished = false;
        public bool IsFinished
        {
            get => _isfinished;
            set
            {
                _isfinished = value;
                if (CanRelease())
                {
                    Pool.Release(this);
                }
            }
        }

        public double Opacity { get; set; } = 1;

        private partial bool CanRelease()
        {
            return Counter > 100 && IsFinished;
        }
        partial void OnReleased()
        {
            _counter = 0;
            _isfinished = false;
            Opacity = 0;
        }
        partial void OnReused()
        {
            Opacity = 1;
        }
    }

StringValidator

Minimal code → reusable string validator

  var validator = new StringValidator()
      .StartWith("Hello")
      .EndWith("World")
      .VarLength(10,22)
      .Include("beautiful")
      .Exclude("bad")
      .Regex(@"^[A-Za-z\s]+$");

  string testString1 = "Hello beautiful World";
  string testString2 = "Hello bad World";

  MessageBox.Show($"{validator.validate(testString1)} | {validator.validate(testString2)}");

RGB

Provides a reference class RGB to describe a color

  • Supporting transition system
  • Edit the values of R, G, B, and A directly
  • Good for color class conversion
  // Some raw data
  string colorText = "Red";
  Color color = Color.FromArgb(0, 0, 0, 0);
  Brush brush = Brushes.Red;

  // Can be converted to RGB
  RGB rgb1 = RGB.FromString(colorText);
  RGB rgb2 = RGB.FromColor(color);
  RGB rgb3 = RGB.FromBrush(brush);

  // RGB is a reference class, but you can use Equals to determine if RGBA is the same
  bool result = rgb1.Equals(rgb3);
  // The hash value is obtained based on RGBA
  int hash = rgb1.GetHashCode();

  // Modify the RGBA value directly
  rgb2.A = rgb1.A;
  rgb2.R = rgb1.R;
  rgb2.G = rgb1.G;
  rgb2.B = rgb1.B;

  // Converting from RGB to other common classes to represent colors
  color = rgb2.Color;
  brush = rgb2.Brush;
Product Compatible and additional computed target framework versions.
.NET net6.0-windows7.0 is compatible.  net7.0-windows was computed.  net8.0-windows was computed.  net8.0-windows7.0 is compatible.  net9.0-windows was computed.  net9.0-windows7.0 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on MinimalisticWPF:

Package Downloads
MinimalisticWPF.Controls

Design some user controls based on [ MinimalisticWPF ]

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
2.9.0 33 2/9/2025
2.8.2 71 1/22/2025
2.8.0 61 1/21/2025