Skip to content

Instantly share code, notes, and snippets.

@battermann
Last active December 8, 2018 00:11
Show Gist options
  • Save battermann/761dd277cb9c3812d6d5 to your computer and use it in GitHub Desktop.
Save battermann/761dd277cb9c3812d6d5 to your computer and use it in GitHub Desktop.
Typesafe conversion of viewmodel property to observable stream
using System.Windows;
namespace PropertyToobsevable
{
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
var vm = new MainWindowViewModel();
var mainWindow = new MainWindow { DataContext = vm };
mainWindow.Show();
}
}
}
<Window x:Class="PropertyToobsevable.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel Margin="10">
<DockPanel>
<Label DockPanel.Dock="Left" Content="Input:" />
<TextBox x:Name="InputTextBox" Focusable="True" Text="{Binding Input, UpdateSourceTrigger=PropertyChanged}"/>
</DockPanel>
<ListBox ItemsSource="{Binding Output}" Margin="0,10,0,0" Height="250"/>
</StackPanel>
</Window>
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reactive.Linq;
using System.Reflection;
namespace PropertyToObsevable
{
public class MainWindowViewModel : INotifyPropertyChanged
{
private string _input;
private ObservableCollection<string> _output = new ObservableCollection<string>();
public ObservableCollection<string> Output
{
get { return _output; }
set
{
if (Equals(Output, value))
return;
_output = value;
OnPropertyChanged("Output");
}
}
public string Input
{
get { return _input; }
set
{
if (Equals(Input, value))
return;
_input = value;
OnPropertyChanged("Input");
}
}
public MainWindowViewModel()
{
this.ToObservable(() => Input)
.Subscribe(Output.Add);
}
private void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
using System;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reactive.Linq;
using System.Reflection;
namespace PropertyToobsevable
{
public static class NotifyPropertyChangedExtensions
{
var memberExpression = propertyExpression.Body as MemberExpression;
return memberExpression == null
? Observable.Empty<T>()
: Observable
.FromEventPattern<PropertyChangedEventArgs>(source, "PropertyChanged")
.Where(e => e.EventArgs.PropertyName == memberExpression.Member.Name)
.SelectMany(_ => source.GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Where(info => info.Name == memberExpression.Member.Name))
.Select(info => (T)info.GetValue(source));
}
}
}
@jakehockey10
Copy link

Was this ever compiled? NotifyPropertyChangedExtensions is not a valid class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment