Friday, February 12, 2016

writing WPF/MVVM ViewModel in C++/CLI

WPF/MVVM fully supported in C# and libraries such as Prism. It is an interesting attempt to use C++/CLI hand-code VM, so that low latency C++ code can send data directly to VM for databinding.

note that C++/CLI only useful for interop, C# is better for CLR. so <msclr/marshal> using namespace msclr::interop; marshal_context ctx; ctx.marshal_as<LPCSTR>() come handy

#pragma once

using namespace System;
using namespace System::ComponentModel;
using namespace System::Reactive;
using namespace System::Reactive::Linq;

namespace JQD{
namespace ViewModels
{
 public ref class MarketWatchViewModel : INotifyPropertyChanged  {
  public:
   MarketWatchViewModel::MarketWatchViewModel()
   {
    IObservable<__int64>^ obs = Observable::Interval(TimeSpan::FromTicks(1)); //1 tick= 100 nano sec, 1 microsecond=1000 ns=1/1000 ms
    Action<__int64>^ a = gcnew Action<__int64>(this, &JQD::ViewModels::MarketWatchViewModel::DoFakeData);
    System::IObserver<__int64>^ obsr = Observer::Create<__int64>(a);
    obs->Subscribe(obsr);
   }
  
   void DoFakeData(__int64 i)
   {
    double x = 1.234;
    double* ptr = &x;
    Price = *ptr*i; // involve native C++ just to test it work still for WPF
   }

   virtual event PropertyChangedEventHandler^ PropertyChanged;
   void NotifyPropertyChanged(String^ propertyName)
   {
    PropertyChanged(this, gcnew PropertyChangedEventArgs(propertyName));
   }

   property String^ Id
   {
    String^ get() { return _id; }
    void set(String^ value) {
     if (value == _id) return;
     NotifyPropertyChanged("Id");
     _id = value;
    }
   }

   property double Price
   {
    double get() { return _price; }
    void set(double value) {
     if (value == _price) return;
     NotifyPropertyChanged("Price");
     _price = value;
   }

  private:
   String^ _id;
   double _price;
  };

}
}

namespace WpfTester
{

public partial class MainWindow : Window
{
 private MarketWatchViewModel vm = new MarketWatchViewModel();

 public MainWindow()
 {
  InitializeComponent();
  DataContext = vm;
 }
}
}

<Window x:Class="WpfTester.MainWindow"
..>
<Grid>
 <Label Content="{Binding Price}" HorizontalAlignment="Left" Height="59" Margin="94,142,0,0" VerticalAlignment="Top" Width="234"/>
</Grid>
</Window>

No comments:

Post a Comment