﻿<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type='text/css' href='https://stocksharp.com/css/style.css'?>
<?xml-stylesheet type='text/css' href='https://stocksharp.com/css/bbeditor.css'?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title type="html">Создание роботов с помощью S#. Часть 5. Использование паттерна MVVM</title>
  <id>~/topic/355/sozdanie-robotov-s-pomoshshyu-s_-chast-5_-ispolzovanie-patterna-mvvm/</id>
  <rights type="text">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  <updated>2026-04-12T18:41:44Z</updated>
  <logo>https://stocksharp.com/images/logo.png</logo>
  <link href="https://stocksharp.com/handlers/atom.ashx?category=topic&amp;id=355" rel="self" type="application/rss+xml" />
  <entry>
    <id>https://stocksharp.com/posts/m/137/</id>
    <title type="text">Можно было бы уже остановиться на достигнутом. Но бородатые дяди в очках все время придумывают какие...</title>
    <published>2012-03-18T21:59:03Z</published>
    <updated>2012-12-17T15:06:40Z</updated>
    <author>
      <name>FinDirector</name>
      <uri>https://stocksharp.com/users/473/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">Можно было бы уже остановиться на достигнутом. Но бородатые дяди в очках все время придумывают какие-то серебрянные пули. Видите ли, уважаемый программист не будет писать кучу кода в форме, а будет использовать паттерн MVVM (Model-View-ViewModel). Не существует какого-то единственно правильного способа реализовать этот паттерн, поэтому предлагаю самый простейший вариант.&lt;br /&gt;Нам понадобится интерфейс IVIew и базовый класс для ViewModel:&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;div class="innercode"&gt;&lt;pre class="brush:csharp"&gt;
	public interface IView
	{
		object DataContext { get; set; }
	}

	public abstract class ViewModel : INotifyPropertyChanged
	{
		public IView View { get; protected set; }

		protected ViewModel() { }

		#region INotifyPropertyChanged Members

		public event PropertyChangedEventHandler PropertyChanged;

		protected void RaisePropertyChanged(string propertyName)
		{
			PropertyChangedEventHandler handler = PropertyChanged;
			if (handler == null) return;
			handler(this, new PropertyChangedEventArgs(propertyName));
		}

		#endregion
	}&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;В нашем простом приложении будет две View и две ViewModel.&lt;br /&gt;&lt;b&gt;StrategyViewModel.cs&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;div class="innercode"&gt;&lt;pre class="brush:csharp"&gt;
	class StrategyViewModel : ViewModel
	{
		public StandardStrategy Strategy { get; private set; }
		public DelegateCommand StartCommand { get; private set; }
		public DelegateCommand StopCommand { get; private set; }
		public DelegateCommand RunTerminalCommand { get; private set; }

		public StrategyViewModel(StandardStrategy strategy)
		{
			this.Strategy = strategy;

			this.StartCommand = new DelegateCommand(OnStartExecuted, CanStart);
			this.StopCommand = new DelegateCommand(OnStopExecuted, CanStop);
			this.RunTerminalCommand = new DelegateCommand(RunTerminal);
			this.Strategy.ProcessStateChanged += s =&amp;gt;
			{
				this.StartCommand.RaiseCanExecuteChanged();
				this.StopCommand.RaiseCanExecuteChanged();
			};

			this.View = new StrategyView();
			this.View.DataContext = this;
		}

		public bool CanStart()
		{
			return Strategy.ProcessState == ProcessStates.Stopped;
		}

		public void OnStartExecuted()
		{
			if (!CanStart())
				return;
			Task.Factory.StartNew(Strategy.Start);
		}

		public bool CanStop()
		{
			return Strategy.ProcessState == ProcessStates.Started;
		}

		public void OnStopExecuted()
		{
			if (!CanStop())
				return;
			MessageBoxResult result = MessageBox.Show(
				String.Format(&amp;quot;Вы уверены, что хотите остановить стратегию {0}?&amp;quot;, Strategy.Name),
				&amp;quot;Подтверждение&amp;quot;, MessageBoxButton.OKCancel);
			if (result == MessageBoxResult.OK)
				Strategy.Stop();
		}

		public void RunTerminal()
		{
			MessageBoxResult result = MessageBox.Show(
				String.Format(&amp;quot;Вы уверены, что хотите запустить терминал {0}?&amp;quot;, Strategy.TraderBuilder.Title),
				&amp;quot;Подтверждение&amp;quot;, MessageBoxButton.OKCancel);
			if (result == MessageBoxResult.OK)
				Strategy.TraderBuilder.RunTerminal();
		}
	}&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;StrategyView помечаем интерфейсом IView:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;StrategyView.xaml.cs&lt;/b&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;div class="innercode"&gt;&lt;pre class="brush:csharp"&gt;
	public partial class StrategyView : UserControl, IView
	{
		public StrategyView()
		{
			InitializeComponent();
		}
	}&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;StrategyView.xaml&lt;/b&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;div class="innercode"&gt;&lt;pre class="brush:xml"&gt;
    &amp;lt;UserControl.Resources&amp;gt;
        &amp;lt;Style x:Key=&amp;quot;stValue&amp;quot; TargetType=&amp;quot;FrameworkElement&amp;quot;&amp;gt;
            &amp;lt;Setter Property=&amp;quot;HorizontalAlignment&amp;quot; Value=&amp;quot;Right&amp;quot; /&amp;gt;
        &amp;lt;/Style&amp;gt;
    &amp;lt;/UserControl.Resources&amp;gt;
    &amp;lt;StackPanel Margin=&amp;quot;3&amp;quot;&amp;gt;
        &amp;lt;StackPanel Margin=&amp;quot;5&amp;quot;&amp;gt;
            &amp;lt;TextBlock Text=&amp;quot;{Binding Strategy.Name}&amp;quot; FontSize=&amp;quot;14&amp;quot; /&amp;gt;
            &amp;lt;TextBlock Text=&amp;quot;{Binding Strategy.Description}&amp;quot; FontSize=&amp;quot;9&amp;quot;  /&amp;gt;
            &amp;lt;Grid&amp;gt;
                &amp;lt;Grid.ColumnDefinitions&amp;gt;
                    &amp;lt;ColumnDefinition /&amp;gt;
                    &amp;lt;ColumnDefinition /&amp;gt;
                &amp;lt;/Grid.ColumnDefinitions&amp;gt;
                &amp;lt;Grid.RowDefinitions&amp;gt;
                    &amp;lt;RowDefinition /&amp;gt;
                    &amp;lt;RowDefinition /&amp;gt;
                    &amp;lt;RowDefinition /&amp;gt;
                    &amp;lt;RowDefinition /&amp;gt;
                    &amp;lt;RowDefinition /&amp;gt;
                    &amp;lt;RowDefinition /&amp;gt;
                &amp;lt;/Grid.RowDefinitions&amp;gt;
                &amp;lt;TextBlock Text=&amp;quot;Терминал: &amp;quot; Grid.Row=&amp;quot;0&amp;quot; Grid.Column=&amp;quot;0&amp;quot; /&amp;gt;
                &amp;lt;Button Grid.Row=&amp;quot;0&amp;quot; Grid.Column=&amp;quot;1&amp;quot;
                                        HorizontalAlignment=&amp;quot;Right&amp;quot;
                                        Content=&amp;quot;{Binding Strategy.TraderBuilder.Title}&amp;quot;
                                        Command=&amp;quot;{Binding Path=RunTerminalCommand}&amp;quot; /&amp;gt;

                &amp;lt;TextBlock Text=&amp;quot;Портфель: &amp;quot; Grid.Row=&amp;quot;1&amp;quot; Grid.Column=&amp;quot;0&amp;quot; /&amp;gt;
                &amp;lt;TextBlock Text=&amp;quot;{Binding Strategy.PortfolioSelector.Title}&amp;quot; Grid.Row=&amp;quot;1&amp;quot; Grid.Column=&amp;quot;1&amp;quot; Style=&amp;quot;{StaticResource stValue}&amp;quot;/&amp;gt;

                &amp;lt;TextBlock Text=&amp;quot;Инструмент: &amp;quot; Grid.Row=&amp;quot;2&amp;quot; Grid.Column=&amp;quot;0&amp;quot; /&amp;gt;
                &amp;lt;TextBlock Text=&amp;quot;{Binding Strategy.SecuritySelector.Title}&amp;quot; Grid.Row=&amp;quot;2&amp;quot; Grid.Column=&amp;quot;1&amp;quot; Style=&amp;quot;{StaticResource stValue}&amp;quot;/&amp;gt;

                &amp;lt;TextBlock Text=&amp;quot;Состояние: &amp;quot; Grid.Row=&amp;quot;3&amp;quot; Grid.Column=&amp;quot;0&amp;quot; /&amp;gt;
                &amp;lt;TextBlock Text=&amp;quot;{Binding Strategy.ProcessState}&amp;quot; Grid.Row=&amp;quot;3&amp;quot; Grid.Column=&amp;quot;1&amp;quot; Style=&amp;quot;{StaticResource stValue}&amp;quot;/&amp;gt;

                &amp;lt;TextBlock Text=&amp;quot;Прибыль: &amp;quot; Grid.Row=&amp;quot;4&amp;quot; Grid.Column=&amp;quot;0&amp;quot;/&amp;gt;
                &amp;lt;TextBlock Text=&amp;quot;{Binding Strategy.PnLManager.PnL}&amp;quot; Grid.Row=&amp;quot;4&amp;quot; Grid.Column=&amp;quot;1&amp;quot; Style=&amp;quot;{StaticResource stValue}&amp;quot;/&amp;gt;

                &amp;lt;TextBlock Text=&amp;quot;Позиция: &amp;quot; Grid.Row=&amp;quot;5&amp;quot; Grid.Column=&amp;quot;0&amp;quot;/&amp;gt;
                &amp;lt;TextBlock Text=&amp;quot;{Binding Strategy.PositionManager.Position}&amp;quot; Grid.Row=&amp;quot;5&amp;quot; Grid.Column=&amp;quot;1&amp;quot; Style=&amp;quot;{StaticResource stValue}&amp;quot;/&amp;gt;
            &amp;lt;/Grid&amp;gt;
            &amp;lt;StackPanel Orientation=&amp;quot;Horizontal&amp;quot; Margin=&amp;quot;0,5,0,0&amp;quot; HorizontalAlignment=&amp;quot;Center&amp;quot;&amp;gt;
                &amp;lt;Button x:Name=&amp;quot;btnStartStrategy&amp;quot; Content=&amp;quot;Старт&amp;quot; Command=&amp;quot;{Binding Path=StartCommand}&amp;quot; Margin=&amp;quot;2,0,0,0&amp;quot; /&amp;gt;
                &amp;lt;Button x:Name=&amp;quot;btnStopStrategy&amp;quot; Content=&amp;quot;Стоп&amp;quot; Command=&amp;quot;{Binding Path=StopCommand}&amp;quot; Margin=&amp;quot;2,0,0,0&amp;quot; /&amp;gt;
            &amp;lt;/StackPanel&amp;gt;
        &amp;lt;/StackPanel&amp;gt;
    &amp;lt;/StackPanel&amp;gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;MainViewModel.cs&lt;/b&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;div class="innercode"&gt;&lt;pre class="brush:csharp"&gt;
	class MainViewModel : IDisposable
	{
		public ObservableCollection&amp;lt;StrategyViewModel&amp;gt; Strategies { get; private set; }
		public ILogListener LogView { get; private set; }
		private LogManager LogManager;

		public MainViewModel()
		{
			Strategies = new ObservableCollection&amp;lt;StrategyViewModel&amp;gt;();
			CreateLoggers();
		}

		private void CreateLoggers()
		{
			LogManager = new LogManager();

			LogView = new StockSharp.Xaml.Monitor();
			LogManager.Listeners.Add(LogView);

			var fileListener = new FileLogListener(
				string.Format(CultureInfo.InvariantCulture, &amp;quot;{0:yyyyMMdd}.txt&amp;quot;, DateTime.Today));
			LogManager.Listeners.Add(fileListener);

			if (!string.IsNullOrEmpty(Settings.GoogleLogin))
			{
				var smsListener = new SmsLogListener(Settings.GoogleLogin, Settings.GooglePassword);
				smsListener.Filters.Add(LogListener.AllErrorFilter);
				LogManager.Listeners.Add(smsListener);
			}
		}

		public void Dispose()
		{
			if (LogManager != null)
				LogManager.Dispose();
			if (Strategies != null)
			{
				foreach (ITraderBuilder traderBuilder in Strategies.Select(s =&amp;gt; s.Strategy.TraderBuilder).Distinct())
				{
					if (traderBuilder != null)
						traderBuilder.Dispose();
				}
			}
		}

		public void LoadStrategies()
		{
			StrategyLoader strategyLoader = StrategyLoader.Load(&amp;quot;Strategies.config&amp;quot;);
			Strategies.Clear();
			foreach (StandardStrategy strategy in strategyLoader.Strategies)
			{
				LogManager.Sources.Add(strategy);
				StrategyViewModel strategyModel = new StrategyViewModel(strategy);
				Strategies.Add(strategyModel);
			}
			foreach (ILogSource logSource in strategyLoader.Strategies
				.Select(s =&amp;gt; s.TraderBuilder).OfType&amp;lt;ILogSource&amp;gt;().Distinct())
			{
				LogManager.Sources.Add(logSource);
			}
		}
	}&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;MainWindow.xaml.cs&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;div class="innercode"&gt;&lt;pre class="brush:csharp"&gt;
	public partial class MainWindow : Window
	{
		private MainViewModel viewModel;

		public MainWindow()
		{
			InitializeComponent();
			this.Loaded += Window_Loaded;

			this.viewModel = new MainViewModel();
			this.DataContext = viewModel;
		}

		private void Window_Loaded(object sender, RoutedEventArgs e)
		{
			viewModel.LoadStrategies();
		}

		protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
		{
			base.OnClosing(e);
			MessageBoxResult result = MessageBox.Show(
				&amp;quot;Вы уверены, что хотите завершить работу?&amp;quot;,
				&amp;quot;Подтверждение&amp;quot;, MessageBoxButton.OKCancel);
			if (result != MessageBoxResult.OK)
				e.Cancel = true;
		}

		protected override void OnClosed(EventArgs e)
		{
			base.OnClosed(e);
			if (viewModel != null)
				viewModel.Dispose();
		}
	}&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;MainWindow.xaml&lt;/b&gt;&lt;br /&gt;&lt;div class="code"&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;div class="innercode"&gt;&lt;pre class="brush:xml"&gt;
    &amp;lt;Grid&amp;gt;
        &amp;lt;Grid.RowDefinitions&amp;gt;
            &amp;lt;RowDefinition Height=&amp;quot;*&amp;quot;/&amp;gt;
            &amp;lt;RowDefinition Height=&amp;quot;*&amp;quot;/&amp;gt;
        &amp;lt;/Grid.RowDefinitions&amp;gt;

        &amp;lt;ScrollViewer Grid.Row=&amp;quot;0&amp;quot; VerticalScrollBarVisibility=&amp;quot;Auto&amp;quot;&amp;gt;
            &amp;lt;ItemsControl ItemsSource=&amp;quot;{Binding Path=Strategies}&amp;quot;&amp;gt;
                &amp;lt;ItemsControl.ItemsPanel&amp;gt;
                    &amp;lt;ItemsPanelTemplate&amp;gt;
                        &amp;lt;WrapPanel &amp;gt;&amp;lt;/WrapPanel&amp;gt;
                    &amp;lt;/ItemsPanelTemplate&amp;gt;
                &amp;lt;/ItemsControl.ItemsPanel&amp;gt;
                &amp;lt;ItemsControl.ItemTemplate&amp;gt;
                    &amp;lt;DataTemplate&amp;gt;
                        &amp;lt;ContentControl Content=&amp;quot;{Binding View}&amp;quot; /&amp;gt;
                    &amp;lt;/DataTemplate&amp;gt;
                &amp;lt;/ItemsControl.ItemTemplate&amp;gt;
            &amp;lt;/ItemsControl&amp;gt;
        &amp;lt;/ScrollViewer&amp;gt;

        &amp;lt;ContentControl Grid.Row=&amp;quot;1&amp;quot; Content=&amp;quot;{Binding LogView}&amp;quot; /&amp;gt;
    &amp;lt;/Grid&amp;gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Остается добавить к приложению стили и оно станет выглядеть как в статье &lt;a href="http://stocksharp.com/algo/article.aspx?aid=4" title="http://stocksharp.com/algo/article.aspx?aid=4"&gt;“Создание роботов с помощью S#. Введение”&lt;/a&gt;.</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/22746/</id>
    <title type="text">Автор использовал using Microsoft.Practices.Prism.Commands; http://compositewpf.codeplex.com/release...</title>
    <published>2012-11-30T17:41:08Z</published>
    <updated>2012-11-30T17:41:08Z</updated>
    <author>
      <name>VassilSanych</name>
      <uri>https://stocksharp.com/users/6491/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">Автор использовал&lt;br /&gt;using Microsoft.Practices.Prism.Commands;&lt;br /&gt;&lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAB1DJoDnRq2AZhPhA8paAWwWEdY6U83fWhkgqk6pCLA8xquyhMXLMnH5TcGAr9puVxQ0zi9Tt5gs6k7bn1IeVu9" title="http://compositewpf.codeplex.com/releases/view/95815"&gt;http://compositewpf.codeplex.com/releases/view/95815&lt;/a&gt;</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/20435/</id>
    <title type="text">По моему скромному мнению, накручивать ViewModel в WPF большого смысла нет. То, что хорошо при напис...</title>
    <published>2012-07-19T10:44:37Z</published>
    <updated>2012-07-19T10:44:37Z</updated>
    <author>
      <name>VassilSanych</name>
      <uri>https://stocksharp.com/users/6491/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;div class="quote"&gt;&lt;span class="quotetitle"&gt;anothar &lt;a href="https://stocksharp.com/posts/m/20354/" class="quote_nav"&gt;&lt;/a&gt;&lt;/span&gt;&lt;div class="innerquote"&gt;&lt;div class="quote"&gt;&lt;span class="quotetitle"&gt;Quote:&lt;/span&gt;&lt;div class="innerquote"&gt;По моему скромному мнению, накручивать ViewModel в WPF большого смысла нет.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;То, что хорошо при написании калькулятора, может не подойти при написании реального приложения.&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt; В &amp;quot;реальном приложении&amp;quot; обычно бывает так:&lt;br /&gt; - архитектор/ведущий разработчик/etc  накрутил 4 звена, в каждом по 5 &amp;quot;правильных&amp;quot; слоёв (действительно правильных со стройной архитектурой),&lt;br /&gt; - документацию по архитектуре ему писать либо лень, либо &amp;quot;потом напишу&amp;quot;, либо она просто устаревает намного быстрее полёта его мысли,&lt;br /&gt; - в команде 10-20 разработчиков,&lt;br /&gt; - все более-менее в курсе зон ответственности звеньев (архитектор за этим старается следить, да VS не даст использовать зависимости чужого звена), но не особо разбираются в идеях зон ответственности слоёв&lt;br /&gt; - соответственно при кодировании зоны ответственности слоёв нарушаются, в проекте хренова туча кода - за каждым не уследишь (при том, что всё замечательно работает и проходит все тесты)&lt;br /&gt; - на выходе имеем жесточайший бардак в проекте -&amp;gt; проблемы с рефакторингом -&amp;gt; медленная и мучительная смерть проекта&lt;br /&gt;&lt;br /&gt;&amp;quot;Сделай настолько просто, насколько это возможно, но не проще.&amp;quot; Эйнштейн &lt;br /&gt;&lt;br /&gt;PS&lt;br /&gt;Я видел это в коде бизнес-приложения Microsoft, например. Кстати это тоже было интеграционное решение, как и StockSharp. C похожими проблемами политики качества (Для обеспечения регрессионного тестирования таких приложений нужно примерно в 3 раза больше ресурсов, чем собственно для создания приложения. Причём ресурсов как минимум такого же качества).&lt;br /&gt;</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/20354/</id>
    <title type="text">По моему скромному мнению, накручивать ViewModel в WPF большого смысла нет. Вот пример ответа на sta...</title>
    <published>2012-07-14T10:04:44Z</published>
    <updated>2012-07-14T10:04:44Z</updated>
    <author>
      <name>anothar</name>
      <uri>https://stocksharp.com/users/6089/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;div class="quote"&gt;&lt;span class="quotetitle"&gt;Quote:&lt;/span&gt;&lt;div class="innerquote"&gt;По моему скромному мнению, накручивать ViewModel в WPF большого смысла нет.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;Вот пример ответа на stackoverflow.com:&lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAADaUgqeUiMvqHjAqLN3xr_cYQ12WhxUIL45Q--L0kVVWtwTzMtuvQm-j2KCmtlRyAaXFXqdah6UrkBHc7sMiyp9" title="http://stackoverflow.com/questions/2798447/is-mvvm-pointless"&gt;wpf mvvm&lt;/a&gt;. Любой паттерн служит определенной цели и модели построения приложений. Нужно его применять там, где он будет востребован и приносить пользу.&lt;br /&gt;&lt;div class="quote"&gt;&lt;span class="quotetitle"&gt;Quote:&lt;/span&gt;&lt;div class="innerquote"&gt;А цель программирования, как известно, - борьба со сложностью. &lt;/div&gt;&lt;/div&gt;&lt;br /&gt;Сложности бывают как известно разные. То, что хорошо при написании калькулятора, может не подойти при написании реального приложения.&lt;br /&gt;Хорошо бы еще раскрыть в статье использование каких-то известных фреймворков типа Prism, Caliburn и т.д.&lt;br /&gt;</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/20350/</id>
    <title type="text"> По моему скромному мнению, накручивать ViewModel в WPF большого смысла нет. Потому что WPF и так ор...</title>
    <published>2012-07-13T16:01:45Z</published>
    <updated>2012-07-13T16:01:45Z</updated>
    <author>
      <name>ra81</name>
      <uri>https://stocksharp.com/users/16581/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;div class="quote"&gt;&lt;span class="quotetitle"&gt;VassilSanych &lt;a href="https://stocksharp.com/posts/m/20348/" class="quote_nav"&gt;&lt;/a&gt;&lt;/span&gt;&lt;div class="innerquote"&gt;&lt;br /&gt;По моему скромному мнению, накручивать ViewModel в WPF большого смысла нет. Потому что WPF и так организован по принципу MVVM.&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;Если системы делаются в виде отдельных библиотек включающих код и отображение, без паттерна не обойтись. Интеграция библиотеки в общую оболочку может встать дорого :). Я тоже реализовал себе сей паттерн. Меня устраиват полностью.&lt;br /&gt;</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/20349/</id>
    <title type="text">Сама стратегия оформляется в виде библиотеки. Кстати. Никто не пробовал csscript? </title>
    <published>2012-07-13T15:43:32Z</published>
    <updated>2012-07-13T15:43:32Z</updated>
    <author>
      <name>VassilSanych</name>
      <uri>https://stocksharp.com/users/6491/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;div class="quote"&gt;&lt;span class="quotetitle"&gt;ra81 &lt;a href="https://stocksharp.com/posts/m/20074/" class="quote_nav"&gt;&lt;/a&gt;&lt;/span&gt;&lt;div class="innerquote"&gt;Сама стратегия оформляется в виде библиотеки. &lt;/div&gt;&lt;/div&gt;&lt;br /&gt;Кстати.&lt;br /&gt;Никто не пробовал &lt;a target="_blank" rel="nofollow" href="https://stocksharp.com/away/?u=AQAAAAAAAAC_lj18XuWpJ9BHq-ZJkHTgAcYye_lXsUTzSY1UzRa7lA" title="http://www.csscript.net/"&gt;csscript&lt;/a&gt;?&lt;br /&gt;&lt;br /&gt;</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/20348/</id>
    <title type="text">Но вообще-то это была шутка (хотя в контексте статьи шуткой и не является). Сейчас объясню почему. П...</title>
    <published>2012-07-13T15:23:42Z</published>
    <updated>2012-07-13T15:39:34Z</updated>
    <author>
      <name>VassilSanych</name>
      <uri>https://stocksharp.com/users/6491/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">Но вообще-то это была шутка (хотя в контексте статьи шуткой и не является).&lt;br /&gt;Сейчас объясню почему.&lt;br /&gt;По моему скромному мнению, накручивать ViewModel в WPF большого смысла нет. Потому что WPF и так организован по принципу MVVM.&lt;br /&gt;Где behind code является фактически этим самым ViewModel (в отличии от форм WinForms), потому что он уже слабо отвечает за отображение формы (должен слабо отвечать), а больше отвечает за её поведение. А в процессе отображения уже участвует не только behind code, но и куча сервисов собственно WPF.&lt;br /&gt;В общем в контексте WPF: view - это XAML, viewModel - это behind code, а model - это собственно модель.&lt;br /&gt;Накручивать свои архитектурные нахлобучки на WPF конечно можно (&amp;quot;Любую проблему можно решить введением дополнительного уровня абстракции, кроме проблемы слишком большого количества уровней абстракции&amp;quot; :)  )&lt;br /&gt;Но, как показывает практика, это обычно усложняет систему и увеличивает трудоёмкость (даже в очень крупных системах). А цель программирования, как известно, - борьба со сложностью. &lt;br /&gt;;)</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/20347/</id>
    <title type="text">Где, где у нас new MainViewModel()? В MainWindow : Window? WinForms Hell detected :) MVVM и рядом не...</title>
    <published>2012-07-13T14:18:23Z</published>
    <updated>2012-07-13T14:18:23Z</updated>
    <author>
      <name>VassilSanych</name>
      <uri>https://stocksharp.com/users/6491/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">Где, где у нас &lt;div class="code"&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;div class="innercode"&gt;&lt;pre class="brush:csharp"&gt;
new MainViewModel()&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;?&lt;br /&gt;В &lt;div class="code"&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;div class="innercode"&gt;&lt;pre class="brush:csharp"&gt;
MainWindow : Window&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;?&lt;br /&gt;WinForms Hell detected :)&lt;br /&gt;MVVM и рядом не стояло. Даже на MVP не тянет :)</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/20082/</id>
    <title type="text">Спасибо за ответ. Все просто и наглядно. </title>
    <published>2012-06-30T14:59:07Z</published>
    <updated>2012-06-30T14:59:07Z</updated>
    <author>
      <name>AlexLan73</name>
      <uri>https://stocksharp.com/users/6005/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">Спасибо за ответ.&lt;br /&gt;Все просто и наглядно.&lt;br /&gt;</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/20074/</id>
    <title type="text">Замечательные примеры. Большое Вам спасибо. А Вы можете сделать пример - вывод индикаторов RSI, MACD...</title>
    <published>2012-06-30T08:00:02Z</published>
    <updated>2012-06-30T08:00:02Z</updated>
    <author>
      <name>ra81</name>
      <uri>https://stocksharp.com/users/16581/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;div class="quote"&gt;&lt;span class="quotetitle"&gt;AlexLan73 &lt;a href="https://stocksharp.com/posts/m/20068/" class="quote_nav"&gt;&lt;/a&gt;&lt;/span&gt;&lt;div class="innerquote"&gt;Замечательные примеры.&lt;br /&gt;Большое Вам спасибо.&lt;br /&gt;А Вы можете сделать пример - вывод индикаторов RSI, MACD ... в новом окне?&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;Я сделал несколько иначе. Сама стратегия оформляется в виде библиотеки. Библиотека подключается в общую систему, в ней же лежит визуализацию самой стратегии. В том числе и кнопка и график.&lt;br /&gt;&lt;br /&gt;По сути система это коробка, куда пихаются кубики.</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/20068/</id>
    <title type="text">Замечательные примеры. Большое Вам спасибо. А Вы можете сделать пример - вывод индикаторов RSI, MACD...</title>
    <published>2012-06-29T17:56:48Z</published>
    <updated>2012-06-29T17:56:48Z</updated>
    <author>
      <name>AlexLan73</name>
      <uri>https://stocksharp.com/users/6005/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">Замечательные примеры.&lt;br /&gt;Большое Вам спасибо.&lt;br /&gt;А Вы можете сделать пример - вывод индикаторов RSI, MACD ... в новом окне?&lt;br /&gt;</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
</feed>