PresentationBase 3.4.0-preview
A lightweight MVVM implementation for WPF (Windows Presentation Foundation) targeting both .NET Framework and .NET (Core).
See the version list below for details.
Install-Package PresentationBase -Version 3.4.0-preview
dotnet add package PresentationBase --version 3.4.0-preview
<PackageReference Include="PresentationBase" Version="3.4.0-preview" />
paket add PresentationBase --version 3.4.0-preview
Take a look at the Quick start in the wiki. Here are some basic examples:
ViewModels with bindable properties
// C# code
public class AwesomeViewModel : ViewModel
{
private string _name;
public string Name
{
get => _name;
set => SetProperty(ref _name, value);
}
}
<!-- XAML -->
<TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />
... and with property validation
// C# code
public class AwesomeViewModel : ViewModel
{
private string _name;
public string Name
{
get => _name;
set => SetProperty(ref _name, value, NameValidation);
}
private IEnumerable<string> NameValidation(string value)
{
if (string.IsNullOrEmpty(value))
yield return "Name cannot be null or empty!";
else if (value == "sungaila")
yield return "Name cannot be stupid!";
}
}
<!-- XAML -->
<TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />
ViewModel collections
// C# code
public class AwesomeViewModel : ViewModel
{
public ObservableViewModelCollection<ChildViewModel> Children { get; }
public AwesomeViewModel()
{
Children = new ObservableViewModelCollection<ChildViewModel>(this);
Children.Add(new ChildViewModel { Nickname = "Blinky" });
Children.Add(new ChildViewModel { Nickname = "Pinky" });
Children.Add(new ChildViewModel { Nickname = "Inky" });
Children.Add(new ChildViewModel { Nickname = "Clyde" });
}
}
<!-- XAML -->
<ListView ItemsSource="{Binding Children}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Nickname}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
... and collection compositions
// C# code
public class AwesomeViewModel : ViewModel
{
public ObservableViewModelCollection<ChildViewModel> Children { get; }
public ObservableViewModelCollection<PersonViewModel> People { get; }
public CompositeViewModelCollection<ViewModel> Composition { get; }
public AwesomeViewModel()
{
Children = new ObservableViewModelCollection<ChildViewModel>(this);
Children.Add(new ChildViewModel { Nickname = "Blinky" });
Children.Add(new ChildViewModel { Nickname = "Pinky" });
Children.Add(new ChildViewModel { Nickname = "Inky" });
Children.Add(new ChildViewModel { Nickname = "Clyde" });
People = new ObservableViewModelCollection<PersonViewModel>(this);
People.Add(new PersonViewModel { Nickname = "Kevin" });
People.Add(new PersonViewModel { Nickname = "Tommy" });
Composition = new CompositeViewModelCollection<ViewModel>();
Composition.Add(Children);
Composition.Add(People);
}
}
<!-- XAML -->
<ListView ItemsSource="{Binding Composition}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Nickname}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Commands
Your command can be defined anywhere you want (as long as its assembly is referenced by the WPF application). Please note that a parameterless constructor (or none at all) is needed.
// C# code
public class AlertCommand : ViewModelCommand<AwesomeViewModel>
{
public override void Execute(AwesomeViewModel parameter)
{
System.Windows.MessageBox.Show("You just clicked that button.");
}
public override bool CanExecute(AwesomeViewModel parameter)
{
return parameter.Name != "John Doe";
}
}
The only reference needed is the x:Type
in XAML. Important: Make sure to write CommandParameter
before Command
to avoid problems with CanExecute
. Consider to create an issue for the .NET Core team (like this one) if you want this WPF bug fixed.
<!-- XAML -->
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Core="clr-namespace:PresentationBase;assembly=PresentationBase"
xmlns:local="clr-namespace:WpfApp">
<Button CommandParameter="{Binding}"
Command="{Core:CommandBinding {x:Type local:AlertCommand}}" />
</Window>
... and async commands
// C# code
public class AlertCommandAsync : ViewModelCommandAsync<AwesomeViewModel>
{
protected override async Task ExecutionAsync(AwesomeViewModel parameter)
{
await Task.Run(() =>
{
System.Threading.Thread.Sleep(2000);
System.Windows.MessageBox.Show("You clicked that button two seconds ago.");
});
}
}
<!-- XAML -->
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Core="clr-namespace:PresentationBase;assembly=PresentationBase"
xmlns:local="clr-namespace:WpfApp">
<Button CommandParameter="{Binding}"
Command="{Core:CommandBinding {x:Type local:AlertCommandAsync}}" />
</Window>
ValueConverters
<!-- XAML -->
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Converters="clr-namespace:PresentationBase.Converters;assembly=PresentationBase"
xmlns:local="clr-namespace:WpfApp">
<TextBox Visibility="{Binding Name, Converter={Converters:NullToVisibilityConverter}}" />
</Window>
Take a look at the Quick start in the wiki. Here are some basic examples:
ViewModels with bindable properties
// C# code
public class AwesomeViewModel : ViewModel
{
private string _name;
public string Name
{
get => _name;
set => SetProperty(ref _name, value);
}
}
<!-- XAML -->
<TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />
... and with property validation
// C# code
public class AwesomeViewModel : ViewModel
{
private string _name;
public string Name
{
get => _name;
set => SetProperty(ref _name, value, NameValidation);
}
private IEnumerable<string> NameValidation(string value)
{
if (string.IsNullOrEmpty(value))
yield return "Name cannot be null or empty!";
else if (value == "sungaila")
yield return "Name cannot be stupid!";
}
}
<!-- XAML -->
<TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />
ViewModel collections
// C# code
public class AwesomeViewModel : ViewModel
{
public ObservableViewModelCollection<ChildViewModel> Children { get; }
public AwesomeViewModel()
{
Children = new ObservableViewModelCollection<ChildViewModel>(this);
Children.Add(new ChildViewModel { Nickname = "Blinky" });
Children.Add(new ChildViewModel { Nickname = "Pinky" });
Children.Add(new ChildViewModel { Nickname = "Inky" });
Children.Add(new ChildViewModel { Nickname = "Clyde" });
}
}
<!-- XAML -->
<ListView ItemsSource="{Binding Children}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Nickname}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
... and collection compositions
// C# code
public class AwesomeViewModel : ViewModel
{
public ObservableViewModelCollection<ChildViewModel> Children { get; }
public ObservableViewModelCollection<PersonViewModel> People { get; }
public CompositeViewModelCollection<ViewModel> Composition { get; }
public AwesomeViewModel()
{
Children = new ObservableViewModelCollection<ChildViewModel>(this);
Children.Add(new ChildViewModel { Nickname = "Blinky" });
Children.Add(new ChildViewModel { Nickname = "Pinky" });
Children.Add(new ChildViewModel { Nickname = "Inky" });
Children.Add(new ChildViewModel { Nickname = "Clyde" });
People = new ObservableViewModelCollection<PersonViewModel>(this);
People.Add(new PersonViewModel { Nickname = "Kevin" });
People.Add(new PersonViewModel { Nickname = "Tommy" });
Composition = new CompositeViewModelCollection<ViewModel>();
Composition.Add(Children);
Composition.Add(People);
}
}
<!-- XAML -->
<ListView ItemsSource="{Binding Composition}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Nickname}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Commands
Your command can be defined anywhere you want (as long as its assembly is referenced by the WPF application). Please note that a parameterless constructor (or none at all) is needed.
// C# code
public class AlertCommand : ViewModelCommand<AwesomeViewModel>
{
public override void Execute(AwesomeViewModel parameter)
{
System.Windows.MessageBox.Show("You just clicked that button.");
}
public override bool CanExecute(AwesomeViewModel parameter)
{
return parameter.Name != "John Doe";
}
}
The only reference needed is the x:Type
in XAML. Important: Make sure to write CommandParameter
before Command
to avoid problems with CanExecute
. Consider to create an issue for the .NET Core team (like this one) if you want this WPF bug fixed.
<!-- XAML -->
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Core="clr-namespace:PresentationBase;assembly=PresentationBase"
xmlns:local="clr-namespace:WpfApp">
<Button CommandParameter="{Binding}"
Command="{Core:CommandBinding {x:Type local:AlertCommand}}" />
</Window>
... and async commands
// C# code
public class AlertCommandAsync : ViewModelCommandAsync<AwesomeViewModel>
{
protected override async Task ExecutionAsync(AwesomeViewModel parameter)
{
await Task.Run(() =>
{
System.Threading.Thread.Sleep(2000);
System.Windows.MessageBox.Show("You clicked that button two seconds ago.");
});
}
}
<!-- XAML -->
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Core="clr-namespace:PresentationBase;assembly=PresentationBase"
xmlns:local="clr-namespace:WpfApp">
<Button CommandParameter="{Binding}"
Command="{Core:CommandBinding {x:Type local:AlertCommandAsync}}" />
</Window>
ValueConverters
<!-- XAML -->
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Converters="clr-namespace:PresentationBase.Converters;assembly=PresentationBase"
xmlns:local="clr-namespace:WpfApp">
<TextBox Visibility="{Binding Name, Converter={Converters:NullToVisibilityConverter}}" />
</Window>
Release Notes
Added .NET 5.0 as a target framework.
Dependencies
-
.NETCoreApp 3.1
- PresentationBase.Core (>= 3.4.0-preview)
-
.NETFramework 4.5
- PresentationBase.Core (>= 3.4.0-preview)
-
.NETFramework 4.8
- PresentationBase.Core (>= 3.4.0-preview)
-
net5.0-windows7.0
- PresentationBase.Core (>= 3.4.0-preview)
Used By
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.