Baike.dev
All toolsOnline toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
G

gemini

> 编程语言
Open source

Gemini is an IDE framework similar in concept to the Visual Studio Shell. It uses AvalonDock and has an MVVM architecture based on Caliburn Micro.

1.1K stars0 likes1 views
WebsiteGitHub

About

Gemini is an IDE framework similar in concept to the Visual Studio Shell. It uses AvalonDock and has an MVVM architecture based on Caliburn Micro.

Gemini

Gemini is a WPF framework designed specifically for building IDE-like applications. It builds on some excellent libraries:

  • AvalonDock (specifically Dirkster99's fork, because it supports .NET Core)
  • Caliburn Micro

Gemini ships with two themes: a Light theme and a Blue theme. There is also an in-development Dark theme.

Getting started

If you are creating a new WPF application, follow these steps:

  • Install the Gemini NuGet package.
  • Delete MainWindow.xaml - you don't need it.
  • Open App.xaml and delete the StartupUri="MainWindow.xaml" attribute.
  • Add xmlns:gemini="http://schemas.timjones.tw/gemini" to App.xaml.
  • Add to a `ResourceDictionary` within.

So the whole App.xaml should look something like this:

xml

    
        
            
                
                    
                
            
        
    

Now hit F5 and see a very empty application!

By far the easiest way to get started with Gemini is to use the various NuGet packages. First, install the base Gemini package (note that the package ID is GeminiWpf, to distinguish it from another NuGet package with the same name):

  • Gemini

Then add any other modules you are interested in (note that some modules have dependencies on other modules, but this is taken care of by the NuGet package dependency system):

  • Gemini.Modules.CodeCompiler
  • Gemini.Modules.CodeEditor
  • Gemini.Modules.ErrorList
  • Gemini.Modules.GraphEditor
  • Gemini.Modules.Inspector
  • Gemini.Modules.Output
  • Gemini.Modules.PropertyGrid

Continuous builds

We use AppVeyor to build Gemini after every commit to the master branch, and also to generate pre-release NuGet packages so you can try out new features immediately.

To access the pre-release NuGet packages, you'll need to add a custom package source in Visual Studio, pointing to this URL:

https://ci.appveyor.com/nuget/gemini-g84phgw340sm

Make sure you select "Include Prerelease" when searching for NuGet packages.

What does it do?

Gemini allows you to build your WPF application by composing separate modules. This provides a nice way of separating out the code for each part of your application. For example, here is a very simple module:

csharp
[Export(typeof(IModule))]
public class Module : ModuleBase
{
	[Import]
	private IPropertyGrid _propertyGrid;

    public override IEnumerable DefaultTools
    {
        get { yield return typeof(IInspectorTool); }
    }

	public override void Initialize()
	{
		var homeViewModel = IoC.Get();
		Shell.OpenDocument(homeViewModel);

		_propertyGrid.SelectedObject = homeViewModel;
	}

	private IEnumerable OpenHome()
	{
		yield return Show.Document();
	}
}

Documents

Documents are (usually) displayed in the main area in the middle of the window. To create a new document type, simply inherit from the Document class:

csharp
public class SceneViewModel : Document
{
	public override string DisplayName
	{
		get { return "3D Scene"; }
	}

	private Vector3 _position;
	public Vector3 Position
	{
        get { return _position; }
        set
        {
            _position = value;
            NotifyOfPropertyChange(() => Position);
        }
	}
}

To open a document, call OpenDocument on the shell (Shell is defined in ModuleBase, but you can also retrieve it from the IoC container with IoC.Get()):

csharp
Shell.OpenDocument(new SceneViewModel());

You can then create a SceneView view, and Caliburn Micro will use a convention-based lookup to find the correct view.

Persisted documents

If you have a document that needs to be loaded from, and saved to, a file, you can use the PersistedDocument base class, to remove a lot of the boilerplate code that you would usually have to write. You only need to implement the DoNew, DoLoad, and DoSave methods.

…

Tools

Tools are usually docked to the sides of the window, although they can also be dragged free to become floating windows. Most of the modules (ErrorList, Output, Toolbox, etc.) primarily provide tools. For example, here is the property grid tool class:

csharp
[Export(typeof(IPropertyGrid))]
public class PropertyGridViewModel : Tool, IPropertyGrid
{
	public PropertyGridViewModel()
	{
		DisplayName = "Properties";
	}

	public override PaneLocation PreferredLocation
	{
		get { return PaneLocation.Right; }
	}

	private object _selectedObject;
	public object SelectedObject
	{
		get { return _selectedObject; }
		set
		{
			_selectedObject = value;
			NotifyOfPropertyChange(() => SelectedObject);
		}
	}
}

For more details on creating documents and tools, look at the demo program and the source code for the built-in modules.

Commands

Commands are one of the core concepts in Gemini. Commands help you to avoid duplicating code by letting you define command handlers in a single place, regardless of whether the command is invoked through a menu item, toolbar item, or other trigger. Gemini's commands are conceptually similar to WPF commands, but they are more powerful.

First, create a command definition. Here's Gemini command definition for opening files:

…

Then, provide a command handler. You can do this in one of two ways. For global commands, that don't depend on a document context, create a global handler:

csharp
[CommandHandler]
public class OpenFileCommandHandler : CommandHandlerBase
{
	public override void Update(Command command)
	{
		// You can enable / disable the command here with:
		// command.Enabled = true;
		
		// You can also modify the command text / icon, which will affect
		// any menu items or toolbar items bound to this command.
	}
	
	public override async Task Run(Command command)
	{
		// ... implement command handling here
	}
}

For commands that depend on a document context, and should be disabled when there is no active document or the active document is not of the correct type, define the command in the document class:

csharp
public class MyDocument : Document, ICommandHandler
{
	void ICommandHandler.Update(Command command)
	{
		command.Enabled = this.Text.Any();
	}

	Task ICommandHandler.Run(Command command)
	{
		this.Text = string.Empty;
		return TaskUtility.Completed;
	}
}

To remove built-in keyboard shortcuts, you can exclude them declaratively:

csharp
[Export]
public static ExcludeCommandKeyboardShortcut ExcludeFileOpenShortcut = new ExcludeCommandKeyboardShortcut(OpenFileCommandDefinition.KeyGesture);

To find out how to bind commands to menus or toolbars, see the "MainMenu" and "ToolBars" modules below.

What modules are built-in?

Gemini itself is built out of seven core modules:

  • MainWindow
  • Shell
  • MainMenu
  • StatusBar
  • ToolBars
  • Toolbox
  • UndoRedo

Several more modules ship with Gemini, and are available as NuGet packages as described above:

  • CodeCompiler
  • CodeEditor
  • ErrorList
  • GraphEditor
  • Inspector
  • Output
  • PropertyGrid

For more information about these modules, see below. In general, each module adds some combination of menu items, tool window, document types and services.

MainWindow module

The main window module:

  • manages the overall window

Provides

  • IMainWindow interface

NuGet package

  • Gemini

Dependencies

  • None

Usage

The IMainWindow interface exposes a number of useful properties to control aspects of the main application window.

csharp
public interface IMainWindow
{
    WindowState WindowState { get; set; }
    double Width { get; set; }
    double Height { get; set; }

    string Title { get; set; }
    ImageSource Icon { get; set; } 

    IShell Shell { get; }
}

Shell module

The shell module:

  • manages placement of the document and tool windows
  • persists and loads the size and position of tool windows
  • manages the links between AvalonDock and Caliburn.Micro

Provides

  • IShell interface

NuGet package

  • Gemini

Dependencies

  • None

Usage

The IShell interface exposes a number of useful properties and methods. It is the main way to control Gemini's behaviour.

csharp
public interface IShell
{
    event EventHandler ActiveDocumentChanging;
    event EventHandler ActiveDocumentChanged;

    bool ShowFloatingWindowsInTaskbar { get; set; }
        
	IMenu MainMenu { get; }
    IToolBars ToolBars { get; }
	IStatusBar StatusBar { get; }

	IDocument ActiveItem { get; }

	IObservableCollection Documents { get; }
	IObservableCollection Tools { get; }

    void ShowTool() where TTool : ITool;
	void ShowTool(ITool model);

	void OpenDocument(IDocument model);
	void CloseDocument(IDocument document);

	void Close();
}

MainMenu module

Adds a main menu to the top of the window.

NuGet package

  • Gemini

Dependencies

  • None

Usage

First, create commands, as described above in the "Commands" section. Then declare menus, menu item groups, and menu items. This is how the built-in File menu and menu items are declared; you can create your own menus in the same way.

csharp
public static class MenuDefinitions
{
    [Export]
    public static readonly MenuDefinition FileMenu = new MenuDefinition(MainMenuBar, 0, Resources.FileMenuText);
	
	[Export]
    public static readonly MenuItemGroupDefinition FileNewOpenMenuGroup = new MenuItemGroupDefinition(FileMenu, 0);
	
	[Export]
    public static readonly MenuItemDefinition FileNewMenuItem = new TextMenuItemDefinition(
        MenuDefinitions.FileNewOpenMenuGroup, 0, "_New");
}

You can either use an existing menu or menu item group as a parent for your menu items, or create your own.

To remove an existing menu item (such as a built-in menu item that you don't want), you can exclude it declaratively:

csharp
[Export]
public static readonly ExcludeMenuItemDefinition ExcludeOpenMenuItem = new ExcludeMenuItemDefinition(Gemini.Modules.Shell.MenuDefinitions.FileOpenMenuItem);

[Export]
public static readonly ExcludeMenuItemGroupDefinition ExcludeWindowMenuItemGroup = new ExcludeMenuItemGroupDefinition(Gemini.Modules.MainMenu.MenuDefinitions.ViewToolsMenuGroup);

[Export]
public static readonly ExcludeMenuDefinition ExcludeWindowMenuDefinition = new ExcludeMenuDefinition(Gemini.Modules.MainMenu.MenuDefinitions.WindowMenu);

StatusBar module

Adds a status bar to the bottom of the window.

Provides

  • IStatusBar
  • StatusBarItemViewModel class

NuGet package

  • Gemini

Dependencies

  • None

Usage

csharp
var statusBar = IoC.Get();
statusBar.AddItem("Hello world!", new GridLength(1, GridUnitType.Star));
statusBar.AddItem("Ln 44", new GridLength(100));
statusBar.AddItem("Col 79", new GridLength(100));

ToolBars module

Adds a toolbar tray to the top of the window. By default, the toolbar tray is hidden - use Shell.ToolBars.Visible = true to show it.

NuGet package

  • [Ge

Issues· 0 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

C#

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言