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. 
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;
}
}
}
}
}
}