0

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.)

1
  • 1
    You need a public property to bind. You have public fields. Commented Jan 4, 2023 at 18:34

1 Answer 1

1

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;
                    }
                }
            }
        }
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Though mostly correct, you need to add the interface INotifyPropertyChanged to your class if you want to use the Property Changed engine
True! Thanks I've completely forgotten to check for It.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.