Home > database >  C# WPF Binding String to Textblock
C# WPF Binding String to Textblock

Time:01-05

I am still a beginner and I'm trying to make a application where a user gets to choose a file. For that I use OpenFileDialog, which has worked fine for me in the past. The file path and content should then be each displayed in a separate textbox. I tried to achieve this by storing the content and path in two strings. Because I want to use those strings later on in my project in another .cs file I figured I make them globally accessable by defining them as public string content = "No file selected yet;. The "No file selected yet" should be the default text before the user has selected anything.

I searched online and tried to accomplish my goals by using DataContext and Binding, but I can't figure out how to make it work. This is the code I have right now:

xaml file:

<UserControl x:Class="Project_Neon.MVVM.View.ChooseFileView"
             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" 
             xmlns:local="clr-namespace:Project_Neon.MVVM.View"
             mc:Ignorable="d" 
             d:DesignHeight="423.4" 
             d:DesignWidth="548.4">

    <StackPanel Background="White">

        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition   Width="20"/>
                <ColumnDefinition   Width="70"/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>

            <Grid.RowDefinitions>
                <RowDefinition  Height="70"/>
                <RowDefinition  Height="100"/>
                <RowDefinition  Height="35"/>
                <RowDefinition  Height="218.4"/>
            </Grid.RowDefinitions>

            <TextBlock  Grid.Column="1"
                        Grid.ColumnSpan="2"
                        Margin="0,5,20,0"
                        Text="Choose File"
                        Foreground="Black"
                        FontSize="28"
                        FontFamily="/Fonts/#Kanit Semi"/>

            <TextBlock  Text="Select the text document with the cheat sheet. &#x0a;Only Documents in a .txt format can be accepted." 
                        Foreground="Black"
                        FontSize="22"
                        FontFamily="/Fonts/#Kanit Light"
                        Grid.Row="1"
                        Grid.Column="1"
                        Grid.ColumnSpan="2"
                        Margin="0,0,20,10"/>

            <Button Grid.Row="2"
                    Grid.Column="1"
                    VerticalAlignment="Top"
                    Content="Select file"
                    Height="25"
                    Width="70"
                    FontFamily="/Fonts/#Kanit"
                    FontSize="14"
                    Style="{StaticResource SelectFileButtonTheme}" 
                    Click="SelectFileButton_Click"/>

            <Grid   Grid.Row="2"
                    Grid.Column="2"
                    Height="25"
                    VerticalAlignment="Top"
                    Margin="0,0,20,0">

                <Border Padding="10" 
                        BorderBrush="#1f1f1f"
                        BorderThickness="1">
                </Border>
                <TextBlock  Name="FilePathDisplay"
                            Text="{Binding Path=CheatFilePath}" 
                            VerticalAlignment="Center"
                            Margin="5,0,0,0"
                            FontSize="14"
                            FontFamily="/Fonts/#Kanit Light"/>
            </Grid>

            <Grid   Grid.Row="3"
                    Grid.Column="1"
                    Grid.ColumnSpan="2"
                    Margin="0,0,20,20">

                <TextBlock  Height="20"
                            VerticalAlignment="Top"
                            Background="#1f1f1f"
                            Foreground="White"
                            Text=" Preview:"
                            FontSize="14"
                            FontFamily="/Fonts/#Kanit"/>
                <Border Padding="10" 
                        BorderBrush="#1f1f1f"
                        BorderThickness="1"
                        Margin="0,20,0,0">
                    <ScrollViewer   HorizontalScrollBarVisibility="Auto"
                                    VerticalScrollBarVisibility="Auto" Margin="-10,-10,-10,-10">
                        <TextBlock  Width="Auto" 
                                    TextWrapping="Wrap"
                                    Text="{Binding Path=CheatFileContent}" 
                                    VerticalAlignment="Top"
                                    FontSize="13"
                                    Margin="1.5,0,1.5,0"
                                    FontFamily="/Fonts/#Kanit Light"/>
                    </ScrollViewer>
                </Border>
            </Grid>
        </Grid>
    </StackPanel>
</UserControl>

and the xaml.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Project_Neon.MVVM.View
{
    /// <summary>
    /// Interaction logic for ChooseFileView.xaml
    /// </summary>

    public partial class ChooseFileView : System.Windows.Controls.UserControl
    {
        public ChooseFileView()
        {
            InitializeComponent();
            this.DataContext = this;
        }

        public string CheatFileContent = "No file selected yet";
        public string CheatFilePath = "No file selected yet";

        private void SelectFileButton_Click(object sender, RoutedEventArgs e)
        {

            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                openFileDialog.InitialDirectory = "c:\\";
                openFileDialog.Filter = ".txt (*.txt)|*.txt";
                openFileDialog.FilterIndex = 1;
                openFileDialog.Multiselect = false;
                openFileDialog.RestoreDirectory = true;

                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    var CheatFileStream = openFileDialog.OpenFile();

                    using (StreamReader reader = new StreamReader(CheatFileStream))
                    {
                        CheatFileContent = reader.ReadToEnd();
                        CheatFilePath = openFileDialog.FileName;
                        OnPropertyChanged(nameof(CheatFilePath));
                        OnPropertyChanged(nameof(CheatFileContent));
                    }
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

I'm afraid that maybe my strings aren't defined right.

(I deleted most of the code from my previous attempts of actually binding the data, because I only got errors.)

CodePudding user response:

As @Andy pointed out you need to bind to properties not fields (check @Marc Gravell answer)

I included the raising of the event inside the setter as it makes more sense

ChooseFileView.xaml.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Project_Neon.MVVM.View
{
    /// <summary>
    /// Interaction logic for ChooseFileView.xaml
    /// </summary>

    public partial class ChooseFileView : System.Windows.Controls.UserControl, System.ComponentModel.INotifyPropertyChanged
    {
        private string _cheatFileContent;
        private string _cheatFilePath;
        
        public event PropertyChangedEventHandler? PropertyChanged;
        
        public string CheatFileContent 
        {
            get => _cheatFileContent;
            set 
            {
                if (_cheatFileContent != value)
                {
                    _cheatFileContent = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CheatFileContent)));
                }
            }
        }
        
        public string CheatFilePath 
        {
            get => _cheatFilePath;
            set 
            {
                if (_cheatFilePath != value)
                {
                    _cheatFilePath = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CheatFilePath)));
                }
            }
        }
        
        public ChooseFileView()
        {
            InitializeComponent();
            this.DataContext = this;
            
            CheatFileContent = "No file selected yet";
            CheatFilePath = "No file selected yet";
        }

        private void SelectFileButton_Click(object sender, RoutedEventArgs e)
        {

            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                openFileDialog.InitialDirectory = "c:\\";
                openFileDialog.Filter = ".txt (*.txt)|*.txt";
                openFileDialog.FilterIndex = 1;
                openFileDialog.Multiselect = false;
                openFileDialog.RestoreDirectory = true;

                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    var CheatFileStream = openFileDialog.OpenFile();

                    using (StreamReader reader = new StreamReader(CheatFileStream))
                    {
                        CheatFileContent = reader.ReadToEnd();
                        CheatFilePath = openFileDialog.FileName;
                    }
                }
            }
        }
    }
}
  • Related