Search code examples
c#wpf

WPF data binding to textbox isn't showing on startup


I'm new to WPF and am still learning about data binding.

I am reading from a file and populating a model with the file data. I would like this data to show in the textboxes when the program starts. However, the data doesn't populate when the program starts, the text boxes are blank. The sets and then the gets are called for both of the properties, and the values are correct, but the text boxes are blank.

Can someone point me in the right direction? What am I missing?

Here is my App.xaml:

    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            MainWindow window = new MainWindow();
            MainWindowViewModel mainWindow = new MainWindowViewModel(GetConfigFile());
            window.DataContext = mainWindow;
        }

        static string GetConfigFile()
        {
            string config = string.Empty;
            string assem = System.Reflection.Assembly.GetExecutingAssembly().Location;
            string path = Path.GetDirectoryName(assem);
            string[] files = Directory.GetFiles(path, "*.xml");
            foreach (string file in files)
            {
                if (file.ToLower().Contains("matrx") || file.ToLower().Contains("matrix"))
                {
                    config = file;
                    break;
                }
            }
            return config;
        }
    }

MainWindowViewModel.cs:

    public class MainWindowViewModel : ViewModelBase
    {
        public Configuration Config { get; set; }

        public MainWindowViewModel(string configFile) 
        {
            base.DisplayName = Resources.MainWindowViewModel_DisplayName;
            Config = new Configuration(configFile);

        }
    }

Configuration.cs:

    public class Configuration : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        string _thisIp;
        public string ThisIp
        { 
            get { return _thisIp; } 
            set 
            { 
                _thisIp = value;
                OnPropertyChanged("ThisIp");
            } 
        }

        string _thisPort;
        public string ThisPort
        { 
            get { return _thisPort; } 
            set 
            { 
                _thisPort = value;
                OnPropertyChanged("ThisPort");
            } 
        }

        public Configuration(string configPath)
        {
            LoadConfig(configPath);
        }

        void LoadConfig(string path)
        {
            if (!String.IsNullOrEmpty(path))
            {
                XElement config;
                using (XmlReader reader = XmlReader.Create(path))
                {
                    config = XElement.Load(reader);
                }
                foreach (XElement node in config.Elements())
                {
                    if (node.Name.ToString().Equals("Device"))
                    {
                        foreach (XElement innerNode in node.Elements())
                        {
                            string name = innerNode.Name.ToString().ToLower();
                            if (name.Equals("ipaddr"))
                            {
                                ThisIp = innerNode.Value;
                            }
                            else if (name.Equals("port"))
                            {
                                ThisPort = innerNode.Value;
                            }
                        }
                        break;
                    }
                }
            }
            else
            {
                // Load defaults
                ThisPort = "7111";
            }
        }

        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

MainWindow.xaml snippet:

<Grid x:Name="Grid_DeviceIP" HorizontalAlignment="Left" VerticalAlignment="Top" Width="450">
    <Grid.Resources >
        <Style TargetType="Border" >
            <Setter Property="Padding" Value="5,5,5,5" />
        </Style>
    </Grid.Resources>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="2*" />
        <ColumnDefinition Width="4*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Label Grid.Row="0" FontWeight="Bold" FontSize="14">Configuration</Label>
    <Border Grid.Row="1" Grid.Column="0">
        <Label HorizontalAlignment="Right">This IP</Label>
    </Border>
        <Border Grid.Row="1" Grid.Column="1">
            <TextBox x:Name="TextBox_ThisIP" Width="275" Text="{Binding Config.ThisIp, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
        </Border>
    <Border Grid.Row="2" Grid.Column="0">
        <Label HorizontalAlignment="Right">This Port</Label>
    </Border>
    <Border Grid.Row="2" Grid.Column="1">
        <TextBox x:Name="TextBox_ThisPort" Width="275" Text="{Binding Config.ThisPort, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
    </Border>
</Grid>

The window: The windwo


Solution

  • Config should be a property (with at least getter), not a field

    public class MainWindowViewModel : ViewModelBase
    {
        public Configuration Config { get; }
    
        public MainWindowViewModel(string configFile) 
        {
            base.DisplayName = Resources.MainWindowViewModel_DisplayName;
            Config = new Configuration(configFile);
    
        }
    }