Как работать с элементами wpf при MVVM

Изучаю построение MVVM в wpf. Делаю тестовый проект для этого. Пока что мне трудно понять эту концепцию, и самое главное как работать с элементами не имея к ним доступа на прямую. Самое простое, не понятно как при такой структуре взять текст из RichTextBox и дальше что то с ним сделать. То есть проблема просто получить объект не имея к нему доступа.

Код:

MainWindow.xaml:

<Window x:Class="TextEditorNetFramework.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TextEditorNetFramework.ViewModel"
        mc:Ignorable="d"
        xmlns:viewModels="clr-namespace:TextEditorNetFramework.ViewModel"
        Title="{Binding Title}" Height="700" Width="1200">
    <Window.DataContext>
        <local:MainVM/>
        <!-- Устанавливаем DataContext -->
    </Window.DataContext>


    <Grid Margin="7,3,0,0">
        <Menu DockPanel.Dock="Top" Margin="-7,-3,7,645">
            <MenuItem Header="Файл">
                <MenuItem Header="Сохранить"/>
            </MenuItem>
        </Menu>

        <TabControl Background="#2b4961" Margin="-6,30,0,0">
            <TabItem Header="Main.txt" BorderThickness="7"  Width="130" Margin="-3,-2,3,0">
                <RichTextBox Foreground="White" x:Name="MainRichTextBox" Background="#2b4961" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" BorderThickness="0" BorderBrush="Black" Height="627" Margin="56,0,-4,0" Padding="3" FontFamily="Segoe UI" FontSize="14">
                </RichTextBox>
            </TabItem>
        </TabControl>
        <Grid x:Name="Test" Margin="-8,53,1138,0" Background="#2b4961"/>
        <Line X1="100" X2="100" Y1="0" Y2="1200" Stroke="Black"
     StrokeThickness="0.3" Margin="-59,55,1083,-5" RenderTransformOrigin="0.764,0.501"/>

    </Grid>
</Window>

MainVM.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using Prism.Mvvm;

namespace TextEditorNetFramework.ViewModel
{
    public class MainVM : BindableBase
    {
        readonly Model.MainModel _model = new Model.MainModel();
        public MainVM()
        {
            _model.PropertyChanged += (s, e) => { RaisePropertyChanged(e.PropertyName); };
        }
        public string Title => _model.Title;
    }
}

MainModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Prism.Mvvm;

namespace TextEditorNetFramework.Model
{
    public class MainModel : BindableBase
    {
        private readonly string _Title = "TextEditor Alpha v0.1";
        public string Title => _Title;
    }
}

В MainWindow.xaml.cs(По сути View) Понятное дело, ничего нет кроме инициализации.

И возвращаемся к сути, как мне банально получить объект моего RichTextBox(Да и вообще другие объекты) для дальнейшего извлечения текста и работы с ним вообще? Или на крайний случай просто сам текст получить. Возможно стоит как то перестроить мой код?


Ответы (1 шт):

Автор решения: John Grave

Подход MVVM призван разделить доступ к данным и визуальную часть.

Во View части будет находиться только ваша разметка. Визуальное представление, никаких манипуляций с контролами (в идеале) в коде быть не должно.

Ваша же ViewModel будет содержать сами данные, с которыми вы работаете (те же текстовые поля, числовые и прочие).

С помощью механизма Binding ваше View получает нотификации об изменении данных в вашей ViewModel. Например так:

class SimpleViewModel : INotifyPropertyChanged
{
  private string _title;
  public string Title
  {
      get { return _title; }
      set
      {
          _title = value;
          OnPropertyChanged("Title");
      }
  }

  public event PropertyChangedEventHandler PropertyChanged;
  public void OnPropertyChanged(string prop)
  {
      if (PropertyChanged != null)
          PropertyChanged(this, new PropertyChangedEventArgs(prop));
  }
}

Тогда в вашем View, к примеру:

<TextBox Text="{Binding Title}" />

Для более подробного разбора, предлагаю вам для начала ознакомиться с интерфейсом INotifyPropertyChanged, прежде чем использовать готовые библиотеки.

→ Ссылка