Troy Frazier
Troy Frazier

Reputation: 391

Textbox.Text not updating in WPF

Warning: I'm a complete WPF noob coming from a Windows forms background.

I have a WPF UserControl, which in turn contains several other UserControls, each meant to display a certain chunk of data from a user's file. One of these controls simply shows name, address, and customer id.

So, my main control looks like so:

<UserControl x:Class="Plus.Gui.FileView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="800" d:DesignWidth="1200" 
             xmlns:gui="clr-namespace:Plus.Gui">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="150*" />
            <RowDefinition Height="150*" />
            <RowDefinition Height="200*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="488*" />
            <ColumnDefinition Width="260*" />
            <ColumnDefinition Width="252*" />
        </Grid.ColumnDefinitions>
        <gui:pnlDebtor Grid.Column="2" HorizontalAlignment="Stretch" x:Name="pDebtor" VerticalAlignment="Stretch" />
    </Grid>
</UserControl>

The pnlDebtor control is the one that should show my info.

The codebehind for my main control looks like so:

using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using MyDataLayer;

namespace Plus.Gui
{
    public partial class FileView : UserControl
    {
        public FileView()
        {
            InitializeComponent();
        }

        public FileView(MyCase file)
        {
            InitializeComponent();
            pDebtor = new pnlDebtor(file);
        }
    }
}

I'm replacing my default pnlDebtor with a new one which loads the data from a file.

Here's the xaml and a part of the codebehind for my pnlDebtor control.

<UserControl x:Class="Plus.Gui.pnlDebtor"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="230" d:DesignWidth="460">
    <Grid>
        <GroupBox Header="Debtor" HorizontalAlignment="Stretch" Margin="0,0,0,0" Name="groupBox1" VerticalAlignment="Stretch">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="28" />
                    <RowDefinition Height="56" />
                    <RowDefinition Height="28" />
                    <RowDefinition />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="80*" />
                    <ColumnDefinition Width="380*" />
                </Grid.ColumnDefinitions>
                <Label Content="Name:" Height="28" HorizontalAlignment="Left" Name="lblName" VerticalAlignment="Top" />
                <Label Content="Address:" Grid.Row="1" Height="28" HorizontalAlignment="Left" Name="lblAddress" VerticalAlignment="Top" />
                <Label Content="Customer Nr.:" Grid.Row="2" Height="28" HorizontalAlignment="Left" Name="lblCustomerNr" VerticalAlignment="Top" />
                <TextBox Grid.Column="1" Height="23" HorizontalAlignment="Stretch" Margin="0,0,0,0" Name="tbName" VerticalAlignment="Top" IsEnabled="False" IsReadOnly="False" />
                <TextBox Grid.Column="1" Grid.Row="1" Height="46" HorizontalAlignment="Stretch" Margin="0,0,0,0" Name="tbAddress" VerticalAlignment="Top" IsReadOnly="False" IsEnabled="True" />
                <TextBox Grid.Column="1" Grid.Row="2" Height="23" HorizontalAlignment="Stretch" Margin="0,0,0,0" Name="tbCustomerNr" VerticalAlignment="Top" IsEnabled="True" IsReadOnly="False" />
                <Button Content="Debtor Details" Grid.ColumnSpan="2" Grid.Row="3" Height="23" HorizontalAlignment="Left" Margin="0,0,0,0" Name="btnDetails" VerticalAlignment="Top" />
            </Grid>
        </GroupBox>
    </Grid>
</UserControl>

public pnlDebtor(MyCase file)
{
    InitializeComponent();
    Contact con = AbstractDataObject.GetObject4ID<Contact>(file.DebtorID);
    string strName = con.Name1;

    if (con.Name2 != null)
        strName += " " + con.Name2;

    if (con.Name3 != null)
        strName += " " + con.Name3;

    if (con.FirstName != null)
        strName += ", " + con.FirstName;

    tbName.Text = strName;
    tbAddress.Text = "test address";
    tbCustomerNr.Text = "test customer id";
}

So, basically, I pass in the file and update the textboxes with the info from the file. Simple. Only, it doesn't work.

If I set a breakpoint after the new pnlDebtor is created, and check the properties, tbName.Text, tbAddress.Text, and tbCustomerNr.Text have indeed been changed. But all the the boxes remain empty in the gui.

If instead of assigning a new pnlDebtor, I simply change the values (pDebtor.tbName.Text = "Dummy") in the codebehind for the FileView control, it works fine.

What am I missing here? Am I not able to replace an existing control with a new one this way?

I've tried setting my original pnlDebtor to null before setting the new control, but got the same results. Somehow my control is being replaced but never being sent to the GUI.

Upvotes: 1

Views: 3989

Answers (2)

matt
matt

Reputation: 333

Looks like you want to use data binding. You can specify the data context for binding in the xaml, or to keep it similar to your existing code you can do it in the code behind:

DataContext = AbstractDatenObjekt.GetObjekt4ID<Contact>(file.DebtorID);

XAML:

<TextBox Text="{Binding strName, Mode=TwoWay}" Grid.Column="1" Height="23" HorizontalAlignment="Stretch" Margin="0,0,0,0" Name="tbName" VerticalAlignment="Top" IsEnabled="False" IsReadOnly="False" />

In your contact class you need to implement INotifyPropertyChanged or use a base case like https://stackoverflow.com/a/1316417/2622972. Once you have that, add a property for strName that calls your version of however you do INotifyPropertyChanged.

Upvotes: 0

Nemanja Banda
Nemanja Banda

Reputation: 861

While you can create controls from code, you should stop thinking in that Windows forms way of creating UI, and read more about how WPF works in general and about data binding.

Basically, you need to bind text box value to string property, and then use the code only to set values of those properties, binding will take care of the rest and update the UI for you.

Upvotes: 1

Related Questions