Skip to content

Commit 490446d

Browse files
author
Sam Storie
committed
Working ViewModel-first child control with Splat (i.e., no autofac yet)
1 parent b51e2eb commit 490446d

File tree

9 files changed

+129
-26
lines changed

9 files changed

+129
-26
lines changed

reactiveui-simple-user-control/SimpleApp/SimpleApp/App.xaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
<Application x:Class="SimpleApp.App"
22
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
33
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4-
xmlns:local="clr-namespace:SimpleApp"
5-
StartupUri="MainWindow.xaml">
4+
xmlns:local="clr-namespace:SimpleApp">
65
<Application.Resources>
76

87
</Application.Resources>

reactiveui-simple-user-control/SimpleApp/SimpleApp/App.xaml.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@
33
using System.Configuration;
44
using System.Data;
55
using System.Linq;
6+
using System.Reflection;
67
using System.Threading.Tasks;
78
using System.Windows;
9+
using ReactiveUI;
10+
using SimpleApp.ViewModels;
11+
using Splat;
812

913
namespace SimpleApp
1014
{
@@ -13,5 +17,17 @@ namespace SimpleApp
1317
/// </summary>
1418
public partial class App : Application
1519
{
20+
public App()
21+
{
22+
// This is the "magic" that automatically registers each view against the IViewFor<>
23+
// interface it implements. This is specific to Splat, and could be replaced by the
24+
// specific capabilities of another IoC library
25+
//
26+
var assembly = Assembly.GetExecutingAssembly();
27+
Locator.CurrentMutable.RegisterViewsForViewModels(assembly);
28+
29+
var view = (Views.MainWindow)Locator.CurrentMutable.GetService(typeof(IViewFor<MainWindowViewModel>));
30+
view.Show();
31+
}
1632
}
1733
}

reactiveui-simple-user-control/SimpleApp/SimpleApp/SimpleApp.csproj

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,21 +75,29 @@
7575
<Generator>MSBuild:Compile</Generator>
7676
<SubType>Designer</SubType>
7777
</ApplicationDefinition>
78-
<Page Include="MainWindow.xaml">
78+
<Page Include="Views\Counter.xaml">
79+
<SubType>Designer</SubType>
80+
<Generator>MSBuild:Compile</Generator>
81+
</Page>
82+
<Page Include="Views\MainWindow.xaml">
7983
<Generator>MSBuild:Compile</Generator>
8084
<SubType>Designer</SubType>
8185
</Page>
8286
<Compile Include="App.xaml.cs">
8387
<DependentUpon>App.xaml</DependentUpon>
8488
<SubType>Code</SubType>
8589
</Compile>
86-
<Compile Include="MainWindow.xaml.cs">
90+
<Compile Include="ViewModels\CounterViewModel.cs" />
91+
<Compile Include="Views\Counter.xaml.cs">
92+
<DependentUpon>Counter.xaml</DependentUpon>
93+
</Compile>
94+
<Compile Include="Views\MainWindow.xaml.cs">
8795
<DependentUpon>MainWindow.xaml</DependentUpon>
8896
<SubType>Code</SubType>
8997
</Compile>
9098
</ItemGroup>
9199
<ItemGroup>
92-
<Compile Include="MainWindowViewModel.cs" />
100+
<Compile Include="ViewModels\MainWindowViewModel.cs" />
93101
<Compile Include="Properties\AssemblyInfo.cs">
94102
<SubType>Code</SubType>
95103
</Compile>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Reactive.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
using ReactiveUI;
8+
9+
namespace SimpleApp.ViewModels
10+
{
11+
public class CounterViewModel : ReactiveObject
12+
{
13+
readonly ObservableAsPropertyHelper<long> _currentValue;
14+
public long CurrentValue => _currentValue.Value;
15+
16+
public CounterViewModel()
17+
{
18+
Observable.Interval(TimeSpan.FromSeconds(1))
19+
.Select(x => x * 2)
20+
.ToProperty(this, x => x.CurrentValue, out _currentValue, 0, false, RxApp.MainThreadScheduler);
21+
22+
}
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,22 @@
11
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
42
using System.Reactive.Linq;
5-
using System.Text;
6-
using System.Threading.Tasks;
73
using ReactiveUI;
84

9-
namespace SimpleApp
5+
namespace SimpleApp.ViewModels
106
{
117
public class MainWindowViewModel : ReactiveObject
128
{
139
readonly ObservableAsPropertyHelper<long> _currentValue;
1410
public long CurrentValue => _currentValue.Value;
1511

12+
public CounterViewModel CounterViewModel { get; }
13+
1614
public MainWindowViewModel()
1715
{
18-
1916
Observable.Interval(TimeSpan.FromSeconds(1))
2017
.ToProperty(this, x => x.CurrentValue, out _currentValue, 0, false, RxApp.MainThreadScheduler);
18+
19+
CounterViewModel = new CounterViewModel();
2120
}
2221
}
2322
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<UserControl x:Class="SimpleApp.Views.Counter"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6+
xmlns:local="clr-namespace:SimpleApp.Views"
7+
mc:Ignorable="d"
8+
d:DesignHeight="300" d:DesignWidth="300">
9+
<DockPanel LastChildFill="True">
10+
<TextBlock DockPanel.Dock="Top" HorizontalAlignment="Center">Counter User Control</TextBlock>
11+
12+
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" x:Name="CurrentValue" FontSize="48"></TextBlock>
13+
</DockPanel>
14+
</UserControl>

reactiveui-simple-user-control/SimpleApp/SimpleApp/MainWindow.xaml.cs renamed to reactiveui-simple-user-control/SimpleApp/SimpleApp/Views/Counter.xaml.cs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,32 +13,38 @@
1313
using System.Windows.Navigation;
1414
using System.Windows.Shapes;
1515
using ReactiveUI;
16+
using SimpleApp.ViewModels;
1617

17-
namespace SimpleApp
18+
namespace SimpleApp.Views
1819
{
1920
/// <summary>
20-
/// Interaction logic for MainWindow.xaml
21+
/// Interaction logic for Counter.xaml
2122
/// </summary>
22-
public partial class MainWindow : Window, IViewFor<MainWindowViewModel>
23+
public partial class Counter : IViewFor<CounterViewModel>
2324
{
24-
public MainWindow()
25+
public static readonly DependencyProperty ViewModelProperty =
26+
DependencyProperty.Register(
27+
"ViewModel",
28+
typeof(CounterViewModel),
29+
typeof(Counter));
30+
31+
public Counter()
2532
{
26-
ViewModel = new MainWindowViewModel();
2733
InitializeComponent();
28-
DataContext = ViewModel;
2934

3035
this.WhenActivated(d =>
3136
{
3237
d(this.OneWayBind(ViewModel, vm => vm.CurrentValue, v => v.CurrentValue.Text));
3338
});
39+
3440
}
3541

3642
object IViewFor.ViewModel
3743
{
38-
get { return ViewModel; }
39-
set { ViewModel = (MainWindowViewModel)value; }
44+
get => ViewModel;
45+
set => ViewModel = (CounterViewModel) value;
4046
}
4147

42-
public MainWindowViewModel ViewModel { get; set; }
48+
public CounterViewModel ViewModel { get; set; }
4349
}
4450
}

reactiveui-simple-user-control/SimpleApp/SimpleApp/MainWindow.xaml renamed to reactiveui-simple-user-control/SimpleApp/SimpleApp/Views/MainWindow.xaml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
<Window x:Class="SimpleApp.MainWindow"
1+
<Window x:Class="SimpleApp.Views.MainWindow"
22
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
33
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
44
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
55
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
66
xmlns:local="clr-namespace:SimpleApp"
7+
xmlns:views="clr-namespace:SimpleApp.Views"
8+
xmlns:reactiveUi="http://reactiveui.net"
79
mc:Ignorable="d"
810
Title="MainWindow" Height="350" Width="525">
911
<Grid Margin="8">
@@ -18,10 +20,6 @@
1820
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" x:Name="CurrentValue" FontSize="48"></TextBlock>
1921
</DockPanel>
2022

21-
<DockPanel Grid.Row="1" LastChildFill="True">
22-
<TextBlock DockPanel.Dock="Top" HorizontalAlignment="Center">Embedded User Control</TextBlock>
23-
24-
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">Nothing yet...</TextBlock>
25-
</DockPanel>
23+
<reactiveUi:ViewModelViewHost Grid.Row="1" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" x:Name="CounterViewModel"></reactiveUi:ViewModelViewHost>
2624
</Grid>
2725
</Window>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System.Windows;
2+
using ReactiveUI;
3+
using SimpleApp.ViewModels;
4+
5+
namespace SimpleApp.Views
6+
{
7+
/// <summary>
8+
/// Interaction logic for MainWindow.xaml
9+
/// </summary>
10+
public partial class MainWindow : Window, IViewFor<MainWindowViewModel>
11+
{
12+
public static readonly DependencyProperty ViewModelProperty =
13+
DependencyProperty.Register(
14+
"ViewModel",
15+
typeof(MainWindowViewModel),
16+
typeof(MainWindow));
17+
18+
public MainWindow()
19+
{
20+
ViewModel = new MainWindowViewModel();
21+
InitializeComponent();
22+
DataContext = ViewModel;
23+
24+
this.WhenActivated(d =>
25+
{
26+
d(this.OneWayBind(ViewModel, vm => vm.CurrentValue, v => v.CurrentValue.Text));
27+
d(this.OneWayBind(ViewModel, vm => vm.CounterViewModel, v => v.CounterViewModel.ViewModel));
28+
});
29+
}
30+
31+
object IViewFor.ViewModel
32+
{
33+
get => ViewModel;
34+
set => ViewModel = (MainWindowViewModel)value;
35+
}
36+
37+
public MainWindowViewModel ViewModel { get; set; }
38+
}
39+
}

0 commit comments

Comments
 (0)