IanHacker
IanHacker

Reputation: 581

textBlock isn't updated (RaisePropertyChanged isn't working?)

My program has two windows. The content of TextBox on MainWindow should change the content of a TextBlock on CalcWindow. However, the TextBlock doesn't change, even after the TextBox is changed.

I added "RaisePropertyChanged" to UISimpleData. So, the content of TextBox is correctly changed. But, it doesn't change the TextBlock on CalcWindow.

MainWindow.xaml

<Window x:Class="DoubleToTextBlockBinding.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="DataUpdate" Height="220.276" Width="400">

    <Grid Height="190" Margin="0,0,-0.667,0" VerticalAlignment="Top">
        <Label Content="Target Value" HorizontalAlignment="Right" Margin="0,0,112,142" VerticalAlignment="Bottom" Width="78"/>
        <TextBox Margin="0,0,24,142" HorizontalAlignment="Right" VerticalAlignment="Bottom" Height="22" Width="60"
                 Text="{Binding DoubleField, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}">
            <TextBox.Style>
                <Style TargetType="{x:Type TextBox}">
                    <Style.Triggers>
                        <Trigger Property="Validation.HasError" Value="true">
                            <Setter Property="ToolTip" Value="{Binding (Validation.Errors)[0].ErrorContent, 
                                RelativeSource={RelativeSource Self}}"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </TextBox.Style>
        </TextBox>
        <TextBlock Text="{Binding DoubleField}" HorizontalAlignment="Right" VerticalAlignment="Bottom" 
                   Margin="0,0,25,115" Height="22" Width="60"/>
        <Button Name="ConfirmButton" Content="Confirm" Margin="85,0,25.666,58" HorizontalAlignment="Right" VerticalAlignment="Bottom" Click="ConfirmButton_Click"/>
    </Grid>
</Window>

MainWindow.xaml.cs

using DoubleToTextBlockBinding.ViewModels;
using DoubleToTextBlockBinding.Views;
using System.Windows;

namespace DoubleToTextBlockBinding
{
    public partial class MainWindow : Window
    {
        private UISimpleData _uiData = new UISimpleData();

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

        private void ConfirmButton_Click(object sender, RoutedEventArgs e)
        {
            new CalcWindow().Show();
        }
    }
}

App.xaml.cs

using System.Windows;

namespace DoubleToTextBlockBinding
{
    public partial class App : Application
    {
        public App()
        {
            System.Windows.FrameworkCompatibilityPreferences
                       .KeepTextBoxDisplaySynchronizedWithTextProperty = false;
        }
    }
}

Views/CalcWindow.xaml

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:viewModels="clr-namespace:DoubleToTextBlockBinding.ViewModels"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        x:Class="DoubleToTextBlockBinding.Views.CalcWindow"
        Title="Bound Window" Width="400" Height="212">
    <Grid>
        <TextBlock Text="{Binding DoubleField}" x:Name="textBox"  Width="104"
            Margin="148,84,0,0" HorizontalAlignment="Left" VerticalAlignment="Top">
            <TextBlock.DataContext>
                <viewModels:UISimpleData/>
            </TextBlock.DataContext>
        </TextBlock>
    </Grid>
</Window>

Views/CalcWindow.xaml.cs

using System.Windows;
using DoubleToTextBlockBinding.ViewModels;

namespace DoubleToTextBlockBinding.Views
{
    public partial class CalcWindow : Window
    {
        private UISimpleData _uiData = new UISimpleData();
        public CalcWindow()
        {
            InitializeComponent();
            this.DataContext = _uiData;
        }
    }
}

ViewModels/UISimpleData.cs

using System;
using System.ComponentModel;
using System.Windows;

namespace DoubleToTextBlockBinding.ViewModels
{
    public class UISimpleData : INotifyPropertyChanged, IDataErrorInfo
    {
        private double _doubleField = 2.0;

        public double DoubleField
        {
            get
            {
                return _doubleField;
            }
            set
            {
                if (_doubleField == value)
                    return;

                _doubleField = value;
                RaisePropertyChanged("DoubleField");
            }
        }

        public string this[string propertyName]
        {
            get
            {
                string validationResult = null;
                switch (propertyName)
                {
                    case "DoubleField":
                        {
                            if (DoubleField < 0 || DoubleField > 5)
                                validationResult = "DoubleField is out of range";
                            break;
                        }
                    default:
                        throw new ApplicationException("Unknown Property being validated on UIData");
                }
                return validationResult;
            }
        }

        public string Error { get { return "Not Implemented"; } }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void RaisePropertyChanged(string property)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
            //MessageBox.Show("Changed to " + DoubleField);
        }
    }
}

Expected behavior:

  1. Change the content of TextBox to "3".

(You will see the TextBlock on the same window changes to "3".)

  1. Click on the "Confirm" button.

  2. A new window appears. Check if the content of the TextBlock is "3".

(The actual result becomes "2" here.)

... This is the best I can do for now. Please help me. Thank you.

Upvotes: 0

Views: 96

Answers (1)

faint220
faint220

Reputation: 111

you are creating new instances of your viewmodel in both classes. If you change something in the viewmodel in MainWindow, you have to pass this model to the CalcWindow.

my guess is that you should write the constructor for CalcWindow like this:

public CalcWindow(UISimpleData yourViewModelFromMainWindow)
{
    InitializeComponent();
    this.DataContext = yourViewModelFromMainWindow;
}

and in the MainWindow, in method ConfirmButton_Click

private void ConfirmButton_Click(object sender, RoutedEventArgs e)
{
    new CalcWindow(this.DataContext as UISimpleData).Show();
}

I hope this is helpful. If it's not, do not hesitate to ask.

Upvotes: 1

Related Questions