This notebook and the C# project in this folder demonstrates how you can use .NET Interactive to embed a kernel within an app, connect to it from another kernel, and use the notebook to send code to the app while it's running.
First, let's start the WPF app and connect to it.
Start-Process -NoNewWindow dotnet run
Once the cell above has finished running, you should see the app's window open. Next, we'll connect to it using a named pipe. The code that sets this up within the WPF app can be seen in App.xaml.cs
.
#!connect named-pipe --kernel-name wpf --pipe-name InteractiveWpf
Kernel added: #!wpf
The topology of connected kernels now looks like this:
flowchart LR
subgraph WPF app
embedded["Embedded C# kernel"]
end
subgraph notebook
CompositeKernel-->n1["C# kernel"]
CompositeKernel-->n2
n2["#!wpf kernel added using #!connect"]--named pipe-->embedded
end
The notebook outputs here are displayed using custom formatters defined within the WPF app itself. Take a look at the file WpfFormatterMixins.cs
.
You'll also notice that you can get completions for the App
object which is exposed to the notebook's kernel by the embedded kernel.
#!wpf
#!dispatcher
using System.Windows.Media;
App.MainWindow.Background = new SolidColorBrush(Colors.Fuchsia);
App.MainWindow.Background
#!wpf
#!dispatcher
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows;
var grid = (Grid)App.MainWindow.Content;
grid.Background = new SolidColorBrush(Colors.CadetBlue);
grid
Create and apply a new view model to the main window.
#!wpf
using System.ComponentModel;
public class TestViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _text = "Notebook Initial Value";
public string Text
{
get => _text;
set
{
if (_text != value)
{
_text = value;
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(nameof(Text)));
}
}
}
}
var vm = new TestViewModel();
#!dispatcher
App.MainWindow.DataContext = vm;
Update the value on the data bound property.
#!wpf
vm.Text = "Value changed!"
Value changed!
Demonstate enabling and disabling running code on the dispatcher.
#!wpf
#!dispatcher --enabled true
//This should work
App.MainWindow.Title = "Done correctly";
#!dispatcher --enabled false
//This is expected to fail
App.MainWindow.Title = "Not so much";