Skip to content

Commit

Permalink
feature: Add ReactivePage for WPF/UWP (#2078)
Browse files Browse the repository at this point in the history
  • Loading branch information
weitzhandler authored and glennawatson committed Jun 18, 2019
1 parent b420e1b commit f9cb151
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ namespace ReactiveUI
public PlatformOperations() { }
public string GetOrientation() { }
}
public abstract class ReactivePage<TViewModel> : System.Windows.Controls.Page, ReactiveUI.IActivatable, ReactiveUI.IViewFor, ReactiveUI.IViewFor<TViewModel>
where TViewModel : class
{
public static readonly System.Windows.DependencyProperty ViewModelProperty;
protected ReactivePage() { }
public TViewModel BindingRoot { get; }
public TViewModel ViewModel { get; set; }
}
public abstract class ReactiveUserControl<TViewModel> : System.Windows.Controls.UserControl, ReactiveUI.IActivatable, ReactiveUI.IViewFor, ReactiveUI.IViewFor<TViewModel>
where TViewModel : class
{
Expand Down
114 changes: 114 additions & 0 deletions src/ReactiveUI/Platforms/windows-common/ReactivePage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Copyright (c) 2019 .NET Foundation and Contributors. All rights reserved.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.

namespace ReactiveUI
{
using System.Diagnostics.CodeAnalysis;
#if NETFX_CORE || HAS_UNO
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
#else
using System.Windows;
using System.Windows.Controls;
#endif

/// <summary>
/// A <see cref="Page"/> that is reactive.
/// </summary>
/// <remarks>
/// <para>
/// This class is a <see cref="Page"/> that is also reactive. That is, it implements <see cref="IViewFor{TViewModel}"/>.
/// You can extend this class to get an implementation of <see cref="IViewFor{TViewModel}"/> rather than writing one yourself.
/// </para>
/// <para>
/// Note that the XAML for your control must specify the same base class, including the generic argument you provide for your view
/// model. To do this, use the <c>TypeArguments</c> attribute as follows:
/// <code>
/// <![CDATA[
/// <rxui:ReactivePage
/// x:Class="Foo.Bar.Views.YourView"
/// x:TypeArguments="vms:YourViewModel"
/// xmlns:rxui="http://reactiveui.net"
/// xmlns:vms="clr-namespace:Foo.Bar.ViewModels"
/// xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
/// xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
/// xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
/// xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
/// mc:Ignorable="d">
/// <!-- view XAML here -->
/// </rxui:ReactivePage>
/// ]]>
/// </code>
/// </para>
/// <para>
/// Note that UWP projects do not support the <c>TypeArguments</c> attribute. The XAML designer window in WPF projects also does not
/// support generic types. To use <see cref="ReactivePage{TViewModel}"/> in XAML documents you need to create a base class
/// where you derive from <see cref="ReactivePage{TViewModel}"/> with the type argument filled in.
/// <code>
/// <![CDATA[
/// internal class YourViewBase : ReactivePage<YourViewModel> { /* No code needed here */ }
///
/// public partial class YourView : YourViewBase
/// {
/// /* Your code */
/// }
/// ]]>
/// </code>
/// Then you can use this base class as root in your XAML document.
/// <code>
/// <![CDATA[
/// <views:YourViewBase
/// x:Class="Foo.Bar.Views.YourView"
/// xmlns:rxui="http://reactiveui.net"
/// xmlns:vms="clr-namespace:Foo.Bar.ViewModels"
/// xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
/// xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
/// xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
/// xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
/// mc:Ignorable="d">
/// <!-- view XAML here -->
/// </views:YourViewBase>
/// ]]>
/// </code>
/// </para>
/// </remarks>
/// <typeparam name="TViewModel">
/// The type of the view model backing the view.
/// </typeparam>
[SuppressMessage("Design", "CA1010:Collections should implement generic interface", Justification = "Deliberate usage")]
public abstract class ReactivePage<TViewModel> :
Page, IViewFor<TViewModel>
where TViewModel : class
{
/// <summary>
/// The view model dependency property.
/// </summary>
public static readonly DependencyProperty ViewModelProperty =
DependencyProperty.Register(
"ViewModel",
typeof(TViewModel),
typeof(ReactivePage<TViewModel>),
new PropertyMetadata(null));

/// <summary>
/// Gets the binding root view model.
/// </summary>
public TViewModel BindingRoot => ViewModel;

/// <inheritdoc/>
public TViewModel ViewModel
{
get => (TViewModel)GetValue(ViewModelProperty);
set => SetValue(ViewModelProperty, value);
}

/// <inheritdoc/>
object IViewFor.ViewModel
{
get => ViewModel;
set => ViewModel = (TViewModel)value;
}
}
}

0 comments on commit f9cb151

Please sign in to comment.