I am having trouble displaying a my data in DataGrid.
I've searched online and found one of the possible solutions or so it seems but still no luck.
I was wondering if you could tell me what's wrong with the code?
FIY: I am loading a .csv into DataTable and then exporting it to DataGrid.
Here is my code:
// DataLoader is a class that loads the data from .csv data file. I've tested it and it works for sure.
// MainWindow.xampl.cs
using System;
using System.Collections.Generic;
using System.Linq;
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 System.Data;
using System.IO;
namespace Splash
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
DataLoader dataTable = new DataLoader();
public MainWindow()
{
InitializeComponent();
}
private void Data_Table(object sender, SelectionChangedEventArgs e)
{
string path = #"C:\Users\Lyukshins\Dropbox\PROGRAM_TEST\AUTOMATION\DATA\Database.csv";
FileInfo theFile = new FileInfo(path);
dataTable = new DataLoader();
DataTable table = dataTable.GetDataTableFromCsv(theFile);
dataGrid.ItemsSource = table.DefaultView;
dataGrid.AutoGenerateColumns = true;
}
private void Copy_Files_Click(object sender, RoutedEventArgs e)
{
}
private void Rename_Click(object sender, RoutedEventArgs e)
{
}
}
}
// XAML
<Window x:Class="Splash.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Splash" mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" d:DesignHeight="386" d:DesignWidth="1000" SizeToContent="WidthAndHeight" Name="Splash" ResizeMode="CanResizeWithGrip" Background="#FFBFDEBF">
<Grid>
<DataGrid Height="335" HorizontalAlignment="Left" Name="dataGrid" VerticalAlignment="Top" Width="475" SelectionChanged="Data_Table"/>
<Button Content="Copy Files" Height="54" HorizontalAlignment="Left" Margin="504,12,0,0" Name="Copy_Files" VerticalAlignment="Top" Width="301" Click="Copy_Files_Click" Foreground="Black" FontStyle="Normal" Background="LightSteelBlue" />
<Button Content="Rename Files" Height="54" HorizontalAlignment="Left" Margin="833,12,0,0" Name="Rename" VerticalAlignment="Top" Width="114" Click="Rename_Click" Background="LightSteelBlue" />
<Button Content="Distribute Files From Vendors" Height="235" HorizontalAlignment="Left" Margin="504,81,0,0" Name="Distribute_Files_From_Vendors" VerticalAlignment="Top" Width="301" Background="LightSteelBlue" />
<Button Content=" Create Project
Folders" Height="235" HorizontalAlignment="Left" Margin="833,81,0,0" Name="Create_Apollo_File_Structure" VerticalAlignment="Top" Width="114" HorizontalContentAlignment="Center" Background="LightSteelBlue" AllowDrop="False"></Button>
</Grid>
</Window>
It seemed that the problem was solved by setting
dataGrid.ItemsSource = table.DefaultView;
dataGrid.AutoGenerateColumns = true;
but it didn't work in my case.
Could you please help?
I was able to get the solution to the problem elsewhere.
The basic idea is that I failed to write a display function.
By simply adding function private void viewGrid(DataTable table) it solved my problem.
Here is the updated code:
using System;
using System.Collections.Generic;
using System.Linq;
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 System.Data;
using System.IO;
namespace Splash
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
DataLoader dataTable = new DataLoader();
public MainWindow()
{
string path = #"C:\Users\Lyukshins\Dropbox\PROGRAM_TEST\AUTOMATION\DATA\Database.csv";
FileInfo theFile = new FileInfo(path);
dataTable = new DataLoader();
DataTable table = dataTable.GetDataTableFromCsv(theFile);
InitializeComponent();
viewGrid(table);
}
private void viewGrid(DataTable table)
{
if (table.Columns.Count == 0)
MessageBox.Show("Error!");
else
dataGrid.ItemsSource = table.DefaultView;
}
private void Data_Table(object sender, SelectionChangedEventArgs e)
{
string path = #"C:\Users\Lyukshins\Dropbox\PROGRAM_TEST\AUTOMATION\DATA\Database.csv";
FileInfo theFile = new FileInfo(path);
dataTable = new DataLoader();
DataTable table = dataTable.GetDataTableFromCsv(theFile);
}
private void Copy_Files_Click(object sender, RoutedEventArgs e)
{
}
private void Rename_Click(object sender, RoutedEventArgs e)
{
}
}
}
Related
This question already has answers here:
Why does WPF support binding to properties of an object, but not fields?
(2 answers)
Closed last month.
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.)
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;
}
}
}
}
}
}
I'm using Material design. I created a color picker to choose the color the user wants, after the user chooses the color and theme.
I want to save these settings into a text file on the disk. I don't know how can I convert these types to a list for the string which can I use for reading theme that is saved :
private void MyColorPicker1_PreviewMouseMove(object sender, MouseEventArgs e)
{
string filepath = #"C:\Themses";
if (e.LeftButton == MouseButtonState.Pressed)
{
ITheme theme = _paletteHelper.GetTheme();
theme.SetPrimaryColor(Color.FromRgb(MyColorPicker1.Color.R, MyColorPicker1.Color.G, MyColorPicker1.Color.B)); //red
var Test = theme.GetBaseTheme();
// something here to write all setting inside of ITheme into the text file
//
_paletteHelper.SetTheme(theme);
}
}
How can I do that?
Full XAML:
<Window x:Class="WpfApp5.SettingThemsWins.MaterialThemSettingy"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp5.SettingThemsWins"
mc:Ignorable="d"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
Background="{DynamicResource MaterialDesignPaper}"
Title="Setting" Height="607" Width="1144" WindowStartupLocation="CenterScreen">
<Grid>
<materialDesign:ColorPicker x:Name="MyColorPicker1" HorizontalAlignment="Left" Margin="20,17,0,0" VerticalAlignment="Top" Height="353" Width="750" PreviewMouseMove="MyColorPicker1_PreviewMouseMove" />
<ToggleButton x:Name="ThemeActivationsBtn" Style="{StaticResource MaterialDesignSwitchToggleButton}" ToolTip="Activation Of Dark Theme" IsChecked="False" Margin="110,380,0,0" Click="ThemeActivationsBtn_Click" HorizontalAlignment="Left" Width="63" Height="27" VerticalAlignment="Top" />
<Label Content="Dark Theme :" HorizontalAlignment="Left" Height="24" Margin="20,382,0,0" VerticalAlignment="Top" Width="85"/>
<Button x:Name="SaverThemy" Content="Save Theme" HorizontalAlignment="Left" Margin="200,375,0,0" VerticalAlignment="Top" Width="170" Click="SaverThemy_Click"/>
</Grid>
</Window>
Code behind:
using MaterialDesignThemes.Wpf;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
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.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace WpfApp5.SettingThemsWins
{
/// <summary>
/// Interaction logic for MaterialThemSettingy.xaml
/// </summary>
public partial class MaterialThemSettingy : Window
{
private readonly PaletteHelper _paletteHelper = new PaletteHelper();
bool isDark;
public MaterialThemSettingy()
{
InitializeComponent();
//EmptySampleWind.Window1 window1 = new EmptySampleWind.Window1();
//window1.Show();
}
public static IEnumerable<string> SortByLength(IEnumerable<string> e)
{
// Use LINQ to sort the array received and return a copy.
var sorted = from s in e
orderby s.Length ascending
select s;
return sorted;
}
private void MyColorPicker1_PreviewMouseMove(object sender, MouseEventArgs e)
{
string filepath = #"C:\Themses";
if (e.LeftButton == MouseButtonState.Pressed)
{
ITheme theme = _paletteHelper.GetTheme();
theme.SetPrimaryColor(Color.FromRgb(MyColorPicker1.Color.R, MyColorPicker1.Color.G, MyColorPicker1.Color.B)); //red
var Test = theme.GetBaseTheme();
// something here to write all setting inside of ITheme into the text file
//
_paletteHelper.SetTheme(theme);
}
}
private void ThemeActivationsBtn_Click(object sender, RoutedEventArgs e)
{
isDark = (bool)ThemeActivationsBtn.IsChecked;
if (isDark)
{
ITheme theme = _paletteHelper.GetTheme();
IBaseTheme baseTheme = isDark ? new MaterialDesignDarkTheme() : (IBaseTheme)new MaterialDesignLightTheme();
theme.SetBaseTheme(baseTheme);
_paletteHelper.SetTheme(theme);
}
else
{
ITheme theme = _paletteHelper.GetTheme();
IBaseTheme baseTheme = isDark ? new MaterialDesignDarkTheme() : (IBaseTheme)new MaterialDesignLightTheme();
theme.SetBaseTheme(baseTheme);
_paletteHelper.SetTheme(theme);
}
}
}
}
I'm having some trouble that I hope you can help with! I've being trying to update this grid.Width parameter in a while loop, in a sleep(500) step. But, when I hit run script on my program, the entire GUI stops. I already tried running the script on a different Thread and using BackgroundWorker, but still both ways they block my application GUI until the script is finished. Could you take a look in the following code please?
using System;
using System.Collections.Generic;
using System.Linq;
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.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.Threading;
using IronPython.Hosting;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
string script;
ScriptEngine engine;
ScriptScope scope;
Thread threadScript;
public MainWindow()
{
InitializeComponent();
engine = Python.CreateEngine();
scope = engine.CreateScope();
string variableName = "isto";
object gridMier = gridScript;
scope.SetVariable(variableName, gridMier);
}
public void rodarScript()
{
this.Dispatcher.Invoke((Action)(() =>
{
try
{
//PARTE PARA ADICIONAR BIBLIOTECAS BASICAS PARA DESENVOLVIMENTO COM OS SCRIPTS
script = #"#Reference the WPF assemblies
import clr
clr.AddReferenceByName(""PresentationFramework, Version = 3.0.0.0, Culture = neutral, PublicKeyToken = 31bf3856ad364e35"")
clr.AddReferenceByName(""PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"")
import System.Windows
def getMyObject():
return isto
objeto = getMyObject()
#Atalhos de referencias para adicionar
Thickness = System.Windows.Thickness
from System.Threading.Thread import Sleep
Debug = System.Diagnostics.Debug";
script = script + "\n" + textBoxScript.Text;
var source = engine.CreateScriptSourceFromString(script, SourceCodeKind.Statements);
//var compiled = source.Compile();
//var result = compiled.Execute(scope);
source.Execute(scope);
}
catch (Exception qualquerExcecaoEncontrada)
{
MessageBox.Show(qualquerExcecaoEncontrada.ToString(), "Scripting Test do Mier", MessageBoxButton.OK);
}
}));
}
private void buttonScript_Click(object sender, RoutedEventArgs e)
{
threadScript = new Thread(rodarScript);
threadScript.Start();
}
}
}
example of the code in IronPython (textBoxScript.Text)
for num in range(1,100):
objeto.Width = objeto.Width + 1
Sleep(500)
This simple code, running on a Thread, blocks my entire GUI for 50 seconds.
Any help would be appreciated!
Thanks,
Lucas.
Creating a seperate thread and then putting the complete content in Dispatcher.Invoke does not sence. Because you are then again sync with the ui thread (the howle time). You should only invoke those things, which needs to be (UI access). First remove that from rodarScript and only use it for script = script + "\n" + textBoxScript.Text;:
public void rodarScript()
{
try
{
//PARTE PARA ADICIONAR BIBLIOTECAS BASICAS PARA DESENVOLVIMENTO COM OS SCRIPTS
script = #"#...";
this.Dispatcher.Invoke((Action)(() =>
{
script = script + "\n" + textBoxScript.Text;
}));
var source = engine.CreateScriptSourceFromString(script, SourceCodeKind.Statements);
//var compiled = source.Compile();
//var result = compiled.Execute(scope);
source.Execute(scope);
}
catch (Exception qualquerExcecaoEncontrada)
{
MessageBox.Show(qualquerExcecaoEncontrada.ToString(), "Scripting Test do Mier", MessageBoxButton.OK);
}
}
(Removed IP-Code).
Then add some simple method, which accepts an instance of PythonFunction and add it as a variable, like this:
public void ExecuteInUI(object obj)
{
this.Dispatcher.BeginInvoke((Action)(() =>
{
var op = engine.CreateOperations(scope);
op.Invoke(obj);
}));
}
Add as variable:
scope.SetVariable("execute_in_ui", new Action<object>(ExecuteInUI));
Then you have to chagne your Python code a little bit, because you only want to use BeginInvoke, when you access the ui:
def inc_width():
objeto.Width = objeto.Width + 1
for num in range(1,100):
execute_in_ui(inc_width)
Sleep(500)
So we are passing the function information of inc_width to c# and execute it from there in ExecuteInUI. Then complete code will look like this:
using System;
using System.Collections.Generic;
using System.Linq;
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.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.Threading;
using IronPython.Hosting;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
namespace AsyncIronPython
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
string script;
ScriptEngine engine;
ScriptScope scope;
Thread threadScript;
public MainWindow()
{
InitializeComponent();
engine = Python.CreateEngine();
scope = engine.CreateScope();
string variableName = "isto";
object gridMier = gridScript;
scope.SetVariable(variableName, gridMier);
scope.SetVariable("execute_in_ui", new Action<object>(ExecuteInUI));
}
public void ExecuteInUI(object obj)
{
this.Dispatcher.BeginInvoke((Action)(() =>
{
var op = engine.CreateOperations(scope);
op.Invoke(obj);
}));
}
public void rodarScript()
{
try
{
//PARTE PARA ADICIONAR BIBLIOTECAS BASICAS PARA DESENVOLVIMENTO COM OS SCRIPTS
script = #"#Reference the WPF assemblies
import clr
clr.AddReferenceByName(""PresentationFramework, Version = 3.0.0.0, Culture = neutral, PublicKeyToken = 31bf3856ad364e35"")
clr.AddReferenceByName(""PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"")
import System.Windows
def getMyObject():
return isto
objeto = getMyObject()
#Atalhos de referencias para adicionar
Thickness = System.Windows.Thickness
from System.Threading.Thread import Sleep
Debug = System.Diagnostics.Debug";
this.Dispatcher.Invoke((Action)(() =>
{
script = script + "\n" + textBoxScript.Text;
}));
var source = engine.CreateScriptSourceFromString(script, SourceCodeKind.Statements);
//var compiled = source.Compile();
//var result = compiled.Execute(scope);
source.Execute(scope);
}
catch (Exception qualquerExcecaoEncontrada)
{
MessageBox.Show(qualquerExcecaoEncontrada.ToString(), "Scripting Test do Mier", MessageBoxButton.OK);
}
}
private void buttonScript_Click(object sender, RoutedEventArgs e)
{
threadScript = new Thread(rodarScript);
threadScript.Start();
}
}
}
XAML:
<Window x:Class="AsyncIronPython.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:AsyncIronPython"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid x:Name="gridScript">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<TextBox x:Name="textBoxScript" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="3" AcceptsReturn="True" AcceptsTab="True" />
<Button x:Name="buttonScript" Click="buttonScript_Click" VerticalAlignment="Center" HorizontalAlignment="Stretch" Content="Execute" Grid.Row="1" Margin="3" />
</Grid>
</Window>
Hope this helps.
Thank you #BengEg and people, that was exactly what I was looking for. I was trying to be able to create animations in textBoxes, Grids, User Controls in general, using IronPython script inside C# WPF. So, I was having trouble to find a way of doing so, since the User Controls are being used by another threads in my program. So, here is the final "Testing Scripting code".
CSharp
using System;
using System.Collections.Generic;
using System.Linq;
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.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.Threading;
using IronPython.Hosting;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
namespace AsyncIronPython
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
string script;
ScriptEngine engine;
ScriptScope scope;
Thread threadScript;
public MainWindow()
{
InitializeComponent();
engine = Python.CreateEngine();
scope = engine.CreateScope();
scope.SetVariable("objetoEditavel", gridScript);
scope.SetVariable("execute_in_ui", new Action<object>(ExecuteInUI));
}
public void ExecuteInUI(object obj)
{
this.Dispatcher.BeginInvoke((Action)(() =>
{
var op = engine.CreateOperations(scope);
op.Invoke(obj);
}));
}
public void rodarScript()
{
try
{
//PARTE PARA ADICIONAR BIBLIOTECAS BASICAS PARA DESENVOLVIMENTO COM OS SCRIPTS
script = #"#Reference the WPF assemblies
import clr
clr.AddReferenceByName(""PresentationFramework, Version = 3.0.0.0, Culture = neutral, PublicKeyToken = 31bf3856ad364e35"")
clr.AddReferenceByName(""PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"")
import System.Windows
def getMyObject():
return objetoEditavel
objeto = getMyObject()
#Atalhos de referencias para adicionar
Thickness = System.Windows.Thickness
from System.Threading.Thread import Sleep
Debug = System.Diagnostics.Debug";
this.Dispatcher.Invoke((Action)(() =>{script = script + "\n" + textBoxScript.Text;}));
var source = engine.CreateScriptSourceFromString(script, SourceCodeKind.Statements);
source.Execute(scope);
}
catch (Exception qualquerExcecaoEncontrada)
{
MessageBox.Show(qualquerExcecaoEncontrada.ToString(), "Scripting Test do Mier", MessageBoxButton.OK);
}
}
private void buttonScript_Click(object sender, RoutedEventArgs e)
{
threadScript = new Thread(rodarScript);
threadScript.Start();
}
}
}
XAML
<Window x:Class="AsyncIronPython.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:AsyncIronPython"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<TextBox x:Name="textBoxScript" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="261,3,3,3" AcceptsReturn="True" AcceptsTab="True" Background="#FFFFD6D6" />
<Button x:Name="buttonScript" Click="buttonScript_Click" VerticalAlignment="Center" HorizontalAlignment="Stretch" Content="Execute" Grid.Row="1" Margin="3" />
<Grid x:Name="gridScript" HorizontalAlignment="Left" Height="50" Margin="10,10,0,0" VerticalAlignment="Top" Width="50" Background="Black"/>
</Grid>
</Window>
IronPython Script inside gridScript (will basically create an animation of this black box grid to grow in a interval of 50 miliseconds.
def inc_width():
objeto.Width = objeto.Width + 1
for num in range(1,100):
execute_in_ui(inc_width)
Sleep(50)
In a WPF application, I have a webbrowser called WebBrowser1. This refers to an HTML page which contains a TextArea to which users can input text.
<html>
<body>
<textarea class="myStudentInput" id="myStudentInput1">
Text to be copied
</textarea>
</body>
</html>
I wish to get this text and potentially also set this text.
I have tried something similar to the javascript way of writing it:
document.getElementById("myStudentOutput1").innerHTML;
such as
HtmlElement textArea = webBrowser1.Document.All["myStudentInput1"];
dynamic textArea = WebBrowser1.Document.GetElementsByID("myStudentInput1").InnerText;
but it doesn't work.
The following solution in Visual Studio 2015 WPF Application works for me.
First, add a reference to the Microsoft HTML COM Library. This is on the COM tab, when you do an "Add Reference" in your project.
Then add the code:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication3"
mc:Ignorable="d"
Title="MainWindow" Height="600" Width="800">
<Grid>
<WebBrowser x:Name="WebBrowser1" HorizontalAlignment="Left" Height="480" Margin="10,10,0,0" VerticalAlignment="Top" Width="770" Source="E:\Others\Dropbox\Programming\Questions.html"/>
<Button x:Name="mySetQuestionButton" Content="Set Question" HorizontalAlignment="Left" Margin="200,520,0,0" VerticalAlignment="Top" Width="75" Click="mySetQuestion"/>
<Button x:Name="myGetAnswerButton" Content="Get Answer" HorizontalAlignment="Left" Margin="350,520,0,0" VerticalAlignment="Top" Width="75" Click="myGetAnswer"/>
<TextBlock x:Name="textBlock" HorizontalAlignment="Left" Margin="600,520,0,0" TextWrapping="Wrap" Text="Hello2" VerticalAlignment="Top"/>
</Grid>
</Window>
and
using System;
using System.Collections.Generic;
using System.Linq;
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.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication3
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void mySetQuestion(object sender, EventArgs e)
{
mshtml.HTMLDocument document = (mshtml.HTMLDocument)WebBrowser1.Document;
mshtml.IHTMLElement textArea = document.getElementById("myQuestion1");
textArea.innerHTML = "What is 1+1?";
}
private void myGetAnswer(object sender, EventArgs e)
{
mshtml.HTMLDocument document = (mshtml.HTMLDocument)WebBrowser1.Document;
mshtml.IHTMLElement textArea = document.getElementById("myStudentInput1");
textBlock.Text = textArea.innerHTML;
}
}
}
but it doesn't work.
I have no idea what that could possibly mean. All you can get is a code snippet that does work:
public partial class Form1 : Form {
private WebBrowser webBrowser1;
private Button button1;
public Form1() {
button1 = new Button { Text = "Test" };
button1.Click += button1_Click;
this.Controls.Add(button1);
webBrowser1 = new WebBrowser { Dock = DockStyle.Fill };
webBrowser1.DocumentText = #"<html><body><textarea class=""myStudentInput"" id=""myStudentInput1"">Text to be copied</textarea></body></html>";
this.Controls.Add(webBrowser1);
}
private void button1_Click(object sender, EventArgs e) {
var elem = webBrowser1.Document.GetElementById("myStudentInput1");
MessageBox.Show(elem.InnerText);
}
}
Which produces:
This question is with reference to my old question here: Primary key in datagrid is always zero
In my previous question, i was working on pretty large database with many relationships, so i thought to give a try to and tested on this basic (very basic)
project.
What i did is i created simple basic wpf application. Added local database with only one table which has two columns.One is id column which is primary key and auto incremented.The other is simple varchar.I added that as data source and created grid from that data source.
here is my xaml:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApplication4" mc:Ignorable="d" x:Class="WpfApplication4.MainWindow"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded_1">
<Window.Resources>
<CollectionViewSource x:Key="tablesViewSource" d:DesignSource="{d:DesignInstance {x:Type local:Table}, CreateList=True}"/>
</Window.Resources>
<Grid DataContext="{StaticResource tablesViewSource}">
<DataGrid x:Name="tablesDataGrid" AutoGenerateColumns="False" EnableRowVirtualization="True" ItemsSource="{Binding}" Margin="47,24,70,95" RowDetailsVisibilityMode="VisibleWhenSelected">
<DataGrid.Columns>
<DataGridTextColumn x:Name="idColumn" Binding="{Binding Id}" Header="Id" Width="SizeToHeader"/>
<DataGridTextColumn x:Name="nameColumn" Binding="{Binding name}" Header="name" Width="SizeToHeader"/>
</DataGrid.Columns>
</DataGrid>
<Button Content="Button" HorizontalAlignment="Left" Margin="221,266,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_1"/>
</Grid>
The only two line of code is written by me. Rest is auto generated.Now i wanted to update my data from gridview, but the big problem is data is not updated.It keep adding zero.
I added entire cs file here.
using System;
using System.Collections.Generic;
using System.Linq;
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.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication4
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private System.Data.Objects.ObjectQuery<Table> GetTablesQuery(Database1Entities database1Entities)
{
System.Data.Objects.ObjectQuery<WpfApplication4.Table> tablesQuery = database1Entities.Tables;
// Returns an ObjectQuery.
return tablesQuery;
}
private void Window_Loaded_1(object sender, RoutedEventArgs e)
{
WpfApplication4.Database1Entities database1Entities = new WpfApplication4.Database1Entities();
// Load data into Tables. You can modify this code as needed.
System.Windows.Data.CollectionViewSource tablesViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("tablesViewSource")));
System.Data.Objects.ObjectQuery<WpfApplication4.Table> tablesQuery = this.GetTablesQuery(database1Entities);
tablesViewSource.Source = tablesQuery.Execute(System.Data.Objects.MergeOption.AppendOnly);
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
var context = new WpfApplication4.Database1Entities();
// Database1Entities db = new Database1Entities();
// db.SaveChanges();
context.SaveChanges();
}
}
}
`
I have started to doubt my basics. Please Help.
This works for me (adjust variable names):
using System.Data.Entity;
private Database1Entities _context = new Database1Entities ();
private void Window_Loaded(object sender, RoutedEventArgs e) {
System.Windows.Data.CollectionViewSource tableViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("tableViewSource")));
_context.Table.Load();
tableViewSource.Source = _context.Table.Local;
}
private void Button_Click(object sender, RoutedEventArgs e) {
_context.SaveChanges();
tableDataGrid.Items.Refresh();
}
More info at: https://msdn.microsoft.com/en-us/data/jj574514.aspx
Try This:
private void Button_Click_1(object sender, RoutedEventArgs e)
{
var context = new WpfApplication4.Database1Entities();
var table = context.Set<YourTable>();
table.Add(new YourTable { Id = id, Name = "John Doe" });
context.SaveChanges();
}