diff --git a/src/Ursa.ReactiveUI/AssemblyInfo.cs b/src/Ursa.ReactiveUI/AssemblyInfo.cs
new file mode 100644
index 0000000..5d28eeb
--- /dev/null
+++ b/src/Ursa.ReactiveUI/AssemblyInfo.cs
@@ -0,0 +1,3 @@
+using Avalonia.Metadata;
+
+[assembly: XmlnsDefinition("https://irihi.tech/ursa", "Ursa.ReactiveUIExtension")]
\ No newline at end of file
diff --git a/src/Ursa.ReactiveUI/ReactiveUrsaView.cs b/src/Ursa.ReactiveUI/ReactiveUrsaView.cs
new file mode 100644
index 0000000..b725b23
--- /dev/null
+++ b/src/Ursa.ReactiveUI/ReactiveUrsaView.cs
@@ -0,0 +1,63 @@
+using Avalonia;
+using ReactiveUI;
+using Ursa.Controls;
+
+/* These codes are ported from Avalonia.ReactiveUI.
+ * **/
+
+namespace Ursa.ReactiveUIExtension;
+///
+/// A ReactiveUI that implements the interface and
+/// will activate your ViewModel automatically if the view model implements .
+/// When the DataContext property changes, this class will update the ViewModel property with the new DataContext
+/// value, and vice versa.
+///
+/// ViewModel type.
+public class ReactiveUrsaView : UrsaView, IViewFor where TViewModel : class
+{
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1002", Justification = "Generic avalonia property is expected here.")]
+ public static readonly StyledProperty ViewModelProperty = AvaloniaProperty
+ .Register, TViewModel?>(nameof(ViewModel));
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public ReactiveUrsaView()
+ {
+ // This WhenActivated block calls ViewModel's WhenActivated
+ // block if the ViewModel implements IActivatableViewModel.
+ this.WhenActivated(disposables => { });
+ }
+
+ ///
+ /// The ViewModel.
+ ///
+ public TViewModel? ViewModel
+ {
+ get => GetValue(ViewModelProperty);
+ set => SetValue(ViewModelProperty, value);
+ }
+
+ object? IViewFor.ViewModel
+ {
+ get => ViewModel;
+ set => ViewModel = (TViewModel?)value;
+ }
+
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ {
+ base.OnPropertyChanged(change);
+
+ if (change.Property == DataContextProperty) {
+ if (ReferenceEquals(change.OldValue, ViewModel)
+ && change.NewValue is null or TViewModel) {
+ SetCurrentValue(ViewModelProperty, change.NewValue);
+ }
+ }
+ else if (change.Property == ViewModelProperty) {
+ if (ReferenceEquals(change.OldValue, DataContext)) {
+ SetCurrentValue(DataContextProperty, change.NewValue);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Ursa.ReactiveUI/ReactiveUrsaWindow.cs b/src/Ursa.ReactiveUI/ReactiveUrsaWindow.cs
new file mode 100644
index 0000000..36d58a5
--- /dev/null
+++ b/src/Ursa.ReactiveUI/ReactiveUrsaWindow.cs
@@ -0,0 +1,63 @@
+using Avalonia;
+using ReactiveUI;
+using Ursa.Controls;
+
+/* These codes are ported from Avalonia.ReactiveUI.
+ * **/
+
+namespace Ursa.ReactiveUIExtension;
+///
+/// A ReactiveUI that implements the interface and will
+/// activate your ViewModel automatically if the view model implements . When
+/// the DataContext property changes, this class will update the ViewModel property with the new DataContext value,
+/// and vice versa.
+///
+/// ViewModel type.
+public class ReactiveUrsaWindow : UrsaWindow, IViewFor where TViewModel : class
+{
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1002", Justification = "Generic avalonia property is expected here.")]
+ public static readonly StyledProperty ViewModelProperty = AvaloniaProperty
+ .Register, TViewModel?>(nameof(ViewModel));
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public ReactiveUrsaWindow()
+ {
+ // This WhenActivated block calls ViewModel's WhenActivated
+ // block if the ViewModel implements IActivatableViewModel.
+ this.WhenActivated(disposables => { });
+ }
+
+ ///
+ /// The ViewModel.
+ ///
+ public TViewModel? ViewModel
+ {
+ get => GetValue(ViewModelProperty);
+ set => SetValue(ViewModelProperty, value);
+ }
+
+ object? IViewFor.ViewModel
+ {
+ get => ViewModel;
+ set => ViewModel = (TViewModel?)value;
+ }
+
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ {
+ base.OnPropertyChanged(change);
+
+ if (change.Property == DataContextProperty) {
+ if (ReferenceEquals(change.OldValue, ViewModel)
+ && change.NewValue is null or TViewModel) {
+ SetCurrentValue(ViewModelProperty, change.NewValue);
+ }
+ }
+ else if (change.Property == ViewModelProperty) {
+ if (ReferenceEquals(change.OldValue, DataContext)) {
+ SetCurrentValue(DataContextProperty, change.NewValue);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Ursa.ReactiveUI/Ursa.ReactiveUIExtension.csproj b/src/Ursa.ReactiveUI/Ursa.ReactiveUIExtension.csproj
new file mode 100644
index 0000000..80bc0ff
--- /dev/null
+++ b/src/Ursa.ReactiveUI/Ursa.ReactiveUIExtension.csproj
@@ -0,0 +1,27 @@
+
+
+
+ netstandard2.0;net8
+ enable
+ latest
+ WCKFWCKY
+ Irihi.Ursa.ReactiveUIExtension
+ irihi.png
+ https://github.com/irihitech/Ursa.Avalonia
+ MIT
+ enable
+ True
+ This is a Ursa expansion. This package integrates and is compatible with UrsaWindow and UrsaView with Avalonia.ReactiveUI. [Avalonia.ReactiveU See: https://docs.avaloniaui.net/zh-Hans/docs/concepts/reactiveui/]
+
+这个是一个Ursa拓展包。这个包整合并互相兼容了UrsaWindow和UrsaView与Avalonia.ReactiveUI的功能。【Avalonia.ReactiveU参见:https://docs.avaloniaui.net/docs/concepts/reactiveui/】
+ 1.0.1
+ WCKFWCKY
+ https://github.com/irihitech/Ursa.Avalonia
+
+
+
+
+
+
+
+
diff --git a/src/Ursa.ReactiveUI/irihi.png b/src/Ursa.ReactiveUI/irihi.png
new file mode 100644
index 0000000..01c68d9
Binary files /dev/null and b/src/Ursa.ReactiveUI/irihi.png differ