0

When I enter text into a Textbox, it updates two TextBlocks at the same time. I'm trying to retrieve that value to save it to a sql database. I've temporarily set it up to display the value in a MessageBox.

ViewModel/Model:

private decimal _amount;

    public decimal Amount
    {
        get
        {
            return _amount;
        }
        set
        {
            _amount = value;
            OnPropertyChanged("Amount");
        }
    }

TextBox Binding:

<TextBox MaxLength="7" Visibility="{Binding Hide1, Converter={StaticResource BoolToVis},FallbackValue=Visible}" Text="{Binding Amount, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Grid.Row="2" />

TextBlocks Binding:

<TextBlock Foreground="Black" Margin="0 0 0 0" VerticalAlignment="Top" Grid.Column="3" Text="{Binding Path=Amount}"/>
<TextBlock Grid.Column="3" Text="{Binding Amount}" Foreground="Black" Margin="0 0 0 0" VerticalAlignment="Bottom"/>

SaveCommand:

private async void Save()
    {
        try
        {
            MessageBox.Show(string.Format("{0}", Amount));
        }
        catch (DbEntityValidationException ex)
        {
            foreach (var en in ex.EntityValidationErrors)
            {
                var exceptionDialog = new MessageDialog
                {
                    Message = { Text = string.Format("{0}, {1}", en.Entry.Entity.GetType().Name, en.Entry.State) }
                };

                await DialogHost.Show(exceptionDialog, "RootDialog");

                foreach (var ve in en.ValidationErrors)
                {
                    exceptionDialog = new MessageDialog
                    {
                        Message = { Text = string.Format("{0}, {1}", ve.PropertyName, ve.ErrorMessage) }
                    };

                    await DialogHost.Show(exceptionDialog, "RootDialog");
                }
            }
        }
        catch(Exception ex)
        {
            var exceptionDialog = new MessageDialog
            {
                Message = { Text = string.Format("{0}", ex) }
            };

            await DialogHost.Show(exceptionDialog, "RootDialog");
        }

    }

When I hit save, the MessageBox displays 0.

EDIT: I've just remembered that I have the ViewModel connected to two UserControls. My TabLayout, which handles the content of TabItems; and Payroll which contains the save button and a TabControl which loads TabLayout into each TabItem.

DataContext for both is:

public TabLayout()
    {
        InitializeComponent();
        DataContext = new PayslipModel();
    }

public Payroll()
    {
        InitializeComponent();
        DataContext = new PayslipModel();
    }
bruh1234
  • 67
  • 10
  • Is all code here part of the same class? Are you sure it's all operating on the same instance of that class? Have you tried debugging this? – Pieter Witvoet Feb 08 '17 at 15:53
  • How/where do you set the datacontext to your ViewModel instance? – TaiT's Feb 08 '17 at 15:56
  • @TaiT's I set it in the code-behind like this `DataContext = new PayslipModel();` – bruh1234 Feb 08 '17 at 15:59
  • @PieterWitvoet Yes, all codes are in the same class and I do believe they're operating on the same instance of that class – bruh1234 Feb 08 '17 at 16:00
  • The posted code should work. At least it works on my machine. Note that when binding to decimal you won't be able to enter a decimal point out of the box see [Binding to decimal](http://stackoverflow.com/questions/14600842/bind-textbox-to-float-value-unable-to-input-dot-comma) To further debug your binding add this `PresentationTraceSources.TraceLevel=High` to your `TextBox` If you see the value going into your property then your Save command is operating on a different instance. In that event post your code behind and how the save command is being called. – JSteward Feb 08 '17 at 16:13
  • Grab Snoop and examine your bindings at runtime. –  Feb 08 '17 at 16:30
  • Please post the code of your code-behind class where you set the DataContext of the window. – mm8 Feb 08 '17 at 16:38
  • @JSteward I'm not sure if I did that right but when I check Live Property Explorer, I see the value in Amount, under DataContext – bruh1234 Feb 08 '17 at 16:46
  • @Will currently checking it out – bruh1234 Feb 08 '17 at 16:46
  • If your setting the value in one of those controls, and trying to save from the other then you've found your problem. Give them both the same instance. – JSteward Feb 08 '17 at 16:58
  • @JSteward That's exactly what I'm trying to do, how can I set them to the same instance? Haven't done that before unfortunately :( – bruh1234 Feb 08 '17 at 17:02
  • @JSteward I just figured it out :) Thanks for the help everyone! – bruh1234 Feb 08 '17 at 17:15
  • Ha! just posted an answer, glad you got it nailed down. – JSteward Feb 08 '17 at 17:17

1 Answers1

1

If you want both controls to share a DataContext then you can inject an instance from your composition root, i.e. App.Xaml.cs The following probably doesn't match the way your application is laid out but should give you the idea. Down the road you can look at dependency injection and how to compose your object graph but this a start.

App.xaml

<Application x:Class="App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"                 
             Startup="OnAppStartup">
    <Application.Resources>

    </Application.Resources>
</Application>

App.xmal.cs

public partial class App : Application {

    private void OnAppStartup(object sender, StartupEventArgs e) {                        
        Application.Current.ShutdownMode = System.Windows.ShutdownMode.OnMainWindowClose;
        var vm = new PayslipModel();
        var mainWindow = new MainWindow(vm);
        Application.Current.MainWindow = mainWindow;
        mainWindow.Show();
    }
}

MainWindow.xaml.cs

public MainWindow(PayslipModel vm){
    InitializeComponent();
    tabControl = new TabControl(vm);
    payRoll = new PayRoll(vm);
}

UserControls

public TabLayout(PayslipModel vm)
{
    InitializeComponent();
    DataContext = vm;
}

public Payroll(PayslipModel vm)
{
    InitializeComponent();
    DataContext = vm;
}
JSteward
  • 6,833
  • 2
  • 21
  • 30
  • I actually did it differently but I've done something similar to what you've posted so it should work too. Thanks for the help again :) – bruh1234 Feb 08 '17 at 17:19