WPF привязка не срабатывает для выбранного элемента

Не могу понять почему моя привязка не работает. Я хочу сделать программу, где можно будет динамически добавлять TextBlock на Canvas и изменять их позиции, размеры и прочие свойства в runtime. Для этого я расширяю классы Canvas и TextBlock в Ecanvas и ETextBlock.

И так у меня есть класс ECanvas, вот важные моменты в нем:

internal class ECanvas : Canvas
{
    public event PropertyChangedEventHandler PropertyChanged;

    private ETextBlock selectedTextBlock;
    public ETextBlock SelectedTextBlock
    {
        get => selectedTextBlock;
        set
        {
            if (selectedTextBlock != null)
                selectedTextBlock.HideBorders();
            Set(ref selectedTextBlock, value);

            if (selectedTextBlock != null)
                selectedTextBlock.ShowBorders();

        }
    }

    public ECanvas()
    {
        this.PreviewMouseMove += ECanvas_PreviewMouseMove;
        this.PreviewMouseLeftButtonUp += ECanvas_PreviewMouseLeftButtonUp;

        ETextBlock tb3 = new ETextBlock();
        tb3.Text = "Im a textBlock3";
        AddTextBlock(tb3);
    }
    
    public void AddTextBlock(UIElement element)
    {
        this.Children.Add(element);
        element.PreviewMouseLeftButtonDown += TextBlock_MouseLeftButtonDown;
    }

    private void TextBlock_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        SelectedTextBlock = (ETextBlock)sender;
        isMoving = true;

        startPoint = e.GetPosition(SelectedTextBlock);
        e.Handled = true;
    }

    protected virtual void OnPropertyChanged([CallerMemberName] string PropertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
    }

    protected virtual bool Set<T>(ref T field, T value, [CallerMemberName] string 
         PropertyName = null)
    {
        if (Equals(field, value)) return false;
        field = value;
        OnPropertyChanged(PropertyName);
        return true;
    }
}

Этот код работает отлично. При клике на нужном мне ETextBlock, SelectedTextBlock меняется и приобретает рамку. Событие PropertyChanged срабатывает. Посмотрим на мою главную viewmodel

internal class VMWindowMain : PropertyChangeNotifier
    {
        private ObservableCollection<FrameworkElement> eCanvasCollection;
        private ECanvas eCanvas;
  

        public ObservableCollection<FrameworkElement> ECanvasCollection
        {
            get { return eCanvasCollection; }
            set
            {
                Set(ref eCanvasCollection, value);
            }
        }

        public ECanvas ECanvas
        {
            get { return eCanvas; }
            set
            {
                Set(ref eCanvas, value);
            }
        }

        public VMWindowMain()
        {
            ECanvas = new ECanvas();
            ECanvasCollection = new ObservableCollection<FrameworkElement>();
            ECanvasCollection.Add(ECanvas);
            ECanvas.SelectedTextBlock.PropertyChanged += SelectedTextBlock_PropertyChanged;
            ECanvas.PropertyChanged += ECanvas_PropertyChanged;
        }

        private void ECanvas_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            _ = ECanvas.SelectedTextBlock.Text;

        }

        private void SelectedTextBlock_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            _= ECanvas.SelectedTextBlock.Text;
        }

Самое интересное, что при изменении свойства Text выбранного ETextBlock событие SelectedTextBlock_PropertyChanged срабатывает. Но если у меня в Canvas более одного ETextBlock, то он постоянно показывает свойства только первого ETextBlock, хотя SelectedTextBlock меняется. То есть, если я выбираю второй ETextBlock и с помощью View меняю свойство Text, то оно меняется в первом ETextBlock, хотя если сделать дебаг в методе по событию ECanvas.SelectedTextBlock.PropertyChanged, то я вижу, что ECanvas.SelectedTextBlock.Text равен второму ETextBlock, но меняется почему то первый.

Ниже представлена View, хотя она не очень интересна.

<Window x:Class="LabelsMaker.Views.Windows.WindowMain"
        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:LabelsMaker.Views.Windows"
        mc:Ignorable="d"
        Title="WindowMain" Height="450" Width="800">
    <Grid>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"></RowDefinition>
                <RowDefinition></RowDefinition>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*"></ColumnDefinition>
                <ColumnDefinition Width="4*"></ColumnDefinition>
            </Grid.ColumnDefinitions>
           
            <ItemsControl Grid.Row="1" Grid.Column="1"
                              ItemsSource="{Binding ECanvasCollection}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <Canvas />
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                </ItemsControl>

            <Grid Grid.Row="1" Grid.Column="0" DataContext="{Binding ECanvas.SelectedTextBlock}">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"></RowDefinition>
                        <RowDefinition Height="Auto"></RowDefinition>
                        <RowDefinition Height="Auto"></RowDefinition>
                        <RowDefinition Height="Auto"></RowDefinition>
                        <RowDefinition Height="Auto"></RowDefinition>
                        <RowDefinition Height="Auto"></RowDefinition>
                        <RowDefinition Height="Auto"></RowDefinition>
                        <RowDefinition Height="Auto"></RowDefinition>
                    </Grid.RowDefinitions>
                    <GroupBox Grid.Row="0" Header ="Текст" >
                        <TextBox Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                    </GroupBox>
                    <GroupBox Grid.Row="1" Header ="Ширина" >
                        <TextBox Text="{Binding Width, UpdateSourceTrigger=PropertyChanged}"/>
                    </GroupBox>
                    <GroupBox Grid.Row="2" Header ="Высота" >
                        <TextBox Text="{Binding Height, UpdateSourceTrigger=PropertyChanged}"/>
                    </GroupBox>
                    <GroupBox Grid.Row="3" Header ="Top" >
                        <TextBox Text="{Binding CanvasTop, UpdateSourceTrigger=PropertyChanged}"/>
                    </GroupBox>
                    <GroupBox Grid.Row="4" Header ="Left" >
                        <TextBox Text="{Binding CanvasLeft, UpdateSourceTrigger=PropertyChanged}"/>
                    </GroupBox>

                    <GroupBox Grid.Row="5" Header ="Шрифт" >
                        <ComboBox ItemsSource="{Binding FontsCollection, UpdateSourceTrigger=PropertyChanged}"
                                 SelectedItem="{Binding TextBlockFontFamily}"/>
                    </GroupBox>

                    <GroupBox Grid.Row="6" Header ="Размер шрифта" >
                        <TextBox Text="{Binding FontSize, UpdateSourceTrigger=PropertyChanged}"/>
                    </GroupBox>
                    
                    <GroupBox Grid.Row="8" Header ="Угол" >
                        <TextBox Text="{Binding Angel, UpdateSourceTrigger=PropertyChanged}"/>
                    </GroupBox>
                </Grid>
            </Grid>
        </Grid>


    </Grid>
</Window>

Прошу помощи, я понятия не имею почему так происходит. Спасибо.


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

Автор решения: Александр Рыбарук

Для того, что бы View видела изменения необходимо было добавить наследование от интерфейса INotifyPropertyChanged

internal class ECanvas : Canvas, INotifyPropertyChanged
{
   ......
}
→ Ссылка