Passing Variables From File-to-File in C# - file

How would I use a variable declared in Program.cs and access it's value from Form1.cs?
I know how to do this in C, but I'm completely lost in Microsoft's little twist on C.
Program.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using LuaInterface;
namespace WindowsFormsApplication1
{
static class Program
{
public static Lua lua = null;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
lua = new Lua();
}
}
}
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using LuaInterface;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
lua.DoString("print('hi')");
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
textBox1.Text = "";
}
}
}

Using your examples of Program.cs and Form1.cs and assuming these are the default names and that you have a Program class that instantiates a Form1 class and that you want to pass a parameter to the Form1 class, you can do the following:
Define a constructor for Form1 that takes this parameter and chain to the default constructor:
private Lua lua;
public Form1(Lua lua) : this()
{
this.lua = lua;
}
In your Program class when instantiating Form1, pass the parameter to it:
lua = new Lua();
Application.Run(new Form1(lua));
Note that I am using OOP terminology - objects and classes (not files).
Update:
Since you have declared your lua variable as a public static member of the Program class, you can access it anywhere in your program (assuming the namespaces have been declared appropriately) as follows:
Program.lua;
Though you would want to instantiate the static field before calling Application.Run.
In any way, this makes the object a public shared resource across all threads - making it virtually untestable and difficult to work with if you go multi-threaded.

You can also access the parameter with
Program.lua;
But Oded's way is cleaner.
And in Main, the object must be instantiated before Application.Run:
static void Main()
{
lua = new Lua();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}

In Program.cs there is most probably a static class defined like this:
static class Program
{
...
}
If you declare the variable as public or internal, you will be able to access it from your form.
static class Program
{
public static int myVariable;
public static int MyProperty { get; set; }
}
In your form, you access the variable and the property with:
int i = Program.myVariable;
int j = Program.MyProperty;
In object-oriented programming, you would usually keep the variables private and only declare the properties as public.

Related

A non-static member reference must be relative to a specific object

I'm trying to get the text in my textbox tb_key to write to my std::string Key Variable by doing this:
std::string Key = TRIPRECOILWARE::LoginForm::tb_key->Text;
I get an error saying :
A non-static member reference must be relative to a specific
object
I tried to search but I couldn't find anything really that fixed it for me.
Minimal Reproducible Example:
LoginForm.h
namespace TRIPRECOILWARE {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
private: System::Void tb_key_TextChanged(System::Object^ sender, System::EventArgs^ e)
{
}
}
LoginForm.cpp
std::string Key = TRIPRECOILWARE::LoginForm::tb_key->Text;
I'm trying to use this in LoginForm.h
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
if (Authenticate(StringToChar(Key), (StringToChar(hwid)))) // Authenticates key & hwid
{
this->Hide();
Software^ soft = gcnew Software();
soft->Show();
}
Basically, I want to get Key from Textbox called tb_key and write
it to my Key variable defined above. Then use that key to
authenticate and perform code
Your real problem is a duplicate of How to turn System::String^ into std::string?
Corrected code:
#include <msclr\marshal.h>
#include <msclr\marshal_cppstd.h>
using namespace System;
using namespace msclr::interop;
void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
std::string Key = marshal_as<std::string>(tb_key->Text);
if (Authenticate(Key.c_str(), hwid.c_str())) // Authenticates key & hwid
{
Hide();
Software^ soft = gcnew Software();
soft->Show();
}
}

render pdf from memorystream

I have searched for entire day for a solution, but somehow I couldn't find it.
What I wanted is to get data from database (binary file such as PDF) into MemoryStream (which I succeeded to do so), but problem is when I wish to preview that file into WebBrowser control.
so the code goes:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.IO;
namespace MemoryStreamTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
MemoryStream memory = new MemoryStream();
//byte[] temp;
private void Form1_Load(object sender, EventArgs e)
{
memory = GetBlobFile();
}
private MemoryStream GetBlobFile()
{
MemoryStream ms = new MemoryStream();
string SQL = "SELECT [SnapshotPDF] FROM [DBtest].[dbo].[SamplePDF] WHERE id = " + 21;
SqlConnection conn = new SqlConnection("Data Source=database;Initial Catalog=DBtest; User ID=test; Password=test;");
SqlCommand comm = new SqlCommand(SQL, conn);
conn.Open();
byte [] result = (byte[])comm.ExecuteScalar();
conn.Close();
if (result != null)
{
ms.Write(result, 0, result.Length);
ms.Position = 0;
}
return ms;
}
private void button1_Click(object sender, EventArgs e)
{
//webBrowser1.DocumentText = "application/pdf";
webBrowser1.DocumentStream = memory;
}
}
}
Actually webBrowser really output content from memory, but obviously from picture above it's rendered as text...
How can I force to render as PDF?
If it is not possible to use webBrowser control, is there any other controls that I can use in WinForms that would preview/render PDF from memory.
You have to implement an async pluggable protocol, e.g. IClassFactory, IInternetProtocol... Then you use CoInternetGetSession to register your protocol. When IE calls your implementation, you can serve your image data from memory/provide mime type.
It's a bit tedious, but doable. Look at IInternetProtocol and pluggable protocols documentation on MSDN.
Done, I found one little bug which I correct it. this is entire code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.IO;
using Ghostscript.NET;
using Ghostscript.NET.Viewer;
namespace MemoryStreamTest
{
public partial class Form1 : Form
{
Stream stream;
byte[] result;
private GhostscriptViewer _viewer;
private GhostscriptVersionInfo _gsVersion = GhostscriptVersionInfo.GetLastInstalledVersion();
private Bitmap _pdfPage = null;
public Form1()
{
InitializeComponent();
pictureBox1.Width = 100;
pictureBox1.Height = 100;
_viewer = new GhostscriptViewer();
_viewer.DisplaySize += new GhostscriptViewerViewEventHandler(_viewer_DisplaySize);
_viewer.DisplayUpdate += new GhostscriptViewerViewEventHandler(_viewer_DisplayUpdate);
_viewer.DisplayPage += new GhostscriptViewerViewEventHandler(_viewer_DisplayPage);
}
private void Form1_Load(object sender, EventArgs e)
{
GetBlobFile();
}
private void GetBlobFile()
{
string SQL = "SELECT [SnapshotPDF] FROM [test].[dbo].[InvoiceAdded] WHERE id = " + 21;
SqlConnection conn = new SqlConnection("Data Source=test;Initial Catalog=test; User ID=test; Password=test;");
SqlCommand comm = new SqlCommand(SQL, conn);
conn.Open();
result = (byte[])comm.ExecuteScalar();
conn.Close();
stream = new MemoryStream(result);
}
private void button1_Click(object sender, EventArgs e)
{
ConvertToBitmap();
}
private void ConvertToBitmap()
{
_viewer.Open(stream, _gsVersion, true);
}
//DisplayPage
void _viewer_DisplayPage(object sender, GhostscriptViewerViewEventArgs e)
{
pictureBox1.Invalidate();
pictureBox1.Update();
}
//DisplaySize - dynamically
void _viewer_DisplaySize(object sender, GhostscriptViewerViewEventArgs e)
{
pictureBox1.Image = e.Image;
}
//DisplayUpdate - automatic update picture
void _viewer_DisplayUpdate(object sender, GhostscriptViewerViewEventArgs e)
{
pictureBox1.Invalidate();
pictureBox1.Update();
}
}
}
keep in mind that for this I needed to add .dll from Ghostscript.NET (a nice wrapper made by my patriot from Croatia), also I needed to install Ghostscript interpreter from GhostScript interpreter
And also many thanks to user: sm.abdullah
which actually point me to right direction.
Cheers

Why does Linq.Enumerable.Where break my ObservableCollection

Background:
I am writing a WPF application, strictly following the MVVM pattern. I have a BaseRepository class as a generic interface for connecting to different databases (EF is not an option), and everything works fine; this is just a technical question.
I use a wrapped ObservableCollection called NotifyingCollection, to subscribe to IEditableObject's ItemEndEdit events (my ViewModelBase entity wrapper implements INotifyPropertyChanged and IEditableObject members).
The provided code sample throws an "'EditItem' is not allowed for this view" exception when the ReadAll method is called upon editing an item in my WPF DataGrid. However, if I replace the line in the method with the commented out part, it works perfectly!
Question:
In other words, it looks like relaying the Linq.Enumerable.Where extension method instead of returning an IEnumerable version of the collection removes functionality from the custom collection; why would that happen if they are both IEnumerable?
Code Sample:
namespace MyCompany.Common.Abstracts
{
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data.Common;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using MyCompany.Common.Extensions;
using MyCompany.Common.Utilities;
public abstract class BaseRepository<TEntity> : IDisposable where TEntity : ViewModelBase
{
protected BaseRepository()
{
this.EntitySet = new NotifyingCollection<TEntity>();
this.EntitySet.ItemEndEdit += new ViewModelBase.ItemEndEditEventHandler(ItemEndEdit);
this.EntitySet.CollectionChanged += new NotifyCollectionChangedEventHandler(CollectionChanged);
}
protected abstract NotifyingCollection<TEntity> EntitySet { get; set; }
protected virtual void PropertyChanged(object sender, PropertyChangedEventArgs e)
{
Debug.WriteLine(String.Format("Modify '{0}'", e.PropertyName), "PropertyChanged");
}
protected virtual void ItemEndEdit(IEditableObject sender)
{
this.Update(sender as TEntity);
}
protected virtual void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
var collection = (e.Action == NotifyCollectionChangedAction.Remove) ?
e.OldItems : e.NewItems;
foreach (TEntity entity in collection)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
entity.PropertyChanged += this.PropertyChanged;
this.Create(entity);
break;
case NotifyCollectionChangedAction.Remove:
entity.PropertyChanged -= this.PropertyChanged;
this.Delete(entity);
break;
default:
Debug.WriteLine(String.Format("{0} '{1}'", e.Action.ToString(), entity.DisplayName), "CollectionChanged");
break;
}
}
}
public virtual bool Create(TEntity entity)
{
Debug.WriteLine(String.Format("Create '{0}'", entity.DisplayName), "CollectionChanged");
return true;
}
public virtual IEnumerable<TEntity> Read(Expression<Func<TEntity, bool>> filter)
{
return this.EntitySet.Where(filter.Compile());
}
public virtual IEnumerable<TEntity> ReadAll()
{
return this.Read(x => true);
//return this.EntitySet;
}
public virtual bool Update(TEntity entity)
{
Debug.WriteLine(String.Format("Update '{0}'", entity.DisplayName), "ItemEndEdit");
return true;
}
public virtual bool Delete(TEntity entity)
{
Debug.WriteLine(String.Format("Delete '{0}'", entity.DisplayName), "CollectionChanged");
return true;
}
public virtual IEnumerable<TColumn> GetColumn<TColumn>(string columnName)
{
var lookupTable = this.Read(x => x != null);
List<TColumn> column = new List<TColumn>();
foreach (TEntity record in lookupTable)
{
column.Add(record.GetPropValue<TColumn>(columnName));
}
var result = column.Distinct();
foreach (TColumn element in result)
{
yield return element;
}
}
public abstract int Commit();
public abstract DbTransaction BeginTransaction();
public abstract void Dispose();
}
}
From MichaelLPerry's blog: Common mistakes while using ObservableCollection
ObservableCollection is imperative. Linq is declarative. The two
cannot be used together without extra help.
Imperative code explicitly acts upon something. When using an
ObservableCollection, you explicitly call Add, Remove, and other
methods to change the collection. You have to decide exactly when and
how to take these actions.
Declarative code implicitly generates something. When using linq, you
declare what a collection will look like, how it will be filtered,
mapped, and transformed. You don’t explicitly modify the collection.
These two paradigms don’t mix. Once you use linq on an
ObservableCollection, it is no longer observable. There are
open-source projects like Bindable Linq that bridge the gap. But
without that extra help, people are often surprised when things don’t
work.
The reurn value of EntitySet.Where method won't be the original NotifyingCollection<TEntity> anymore.

Force validation on bound controls from XAML?

There is a very similar question already posted. In fact, the result of the answer in that post is exactly what I'm after, but I have no codebehind to place that code in. All of our logic is encapsulated in a ViewModel. Since the ViewModel is not supposed to have direct references to specific visual elements, this code cannot exist there either. Is there a way to perform this same thing in XAML somehow, or have I finally ran into a reason to be forced to create codebehind files?
You could try doing something with attached properties..it's a bit elaborate, but it does the same as the other answer, so i think it should work:
public class DependencyPropertyCollection : List<DependencyProperty>
{ }
public static class ValidationUtil
{
public static readonly DependencyProperty ForceValidationProperty =
DependencyProperty.RegisterAttached("ForceValidation", typeof(DependencyPropertyCollection), typeof(ValidationUtil), new PropertyMetadata(OnForceValidationChanged));
private static void OnForceValidationChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
FrameworkElement element = (FrameworkElement)sender;
element.Loaded += OnElementLoaded;
}
private static void OnElementLoaded(object sender, RoutedEventArgs e)
{
FrameworkElement element = (FrameworkElement)sender;
element.Loaded -= OnElementLoaded;
foreach (DependencyProperty property in GetForceValidation(element))
element.GetBindingExpression(property).UpdateSource();
}
public static DependencyPropertyCollection GetForceValidation(DependencyObject obj)
{
return (DependencyPropertyCollection)obj.GetValue(ForceValidationProperty);
}
public static void SetForceValidation(DependencyObject obj, DependencyPropertyCollection value)
{
obj.SetValue(ForceValidationProperty, value);
}
}
And you use it like this:
<TextBlock Text="{Binding Text}">
<local:ValidationUtil.ForceValidation>
<local:DependencyPropertyCollection>
<x:StaticExtension Member="TextBlock.TextProperty"/>
</local:DependencyPropertyCollection>
</local:ValidationUtil.ForceValidation>
</TextBlock>
Inside the collection you specify each DependencyProperty which has a binding that you want to validate.

How to save an stringbuilder's content to text file using SaveFileDialog?

This is a winforms application.
In windows, I want the user to click and button, and then a popup should make the user select the path of where they want to save the file.
You want the WriteAllText function.
using (SaveFileDialog dialog = new SaveFileDialog()) {
if (dialog.ShowDialog(this) == DialogResult.OK) {
File.WriteAllText(dialog.FileName, yourStringBuilder.ToString());
}
}
Think no longer...
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication2 {
public partial class Form1 : Form {
StringBuilder sb = new StringBuilder();
public Form1() {
InitializeComponent();
sb.Append("This is going ");
sb.Append("to be saved to a text file");
}
private void button1_Click(object sender, EventArgs e) {
using (SaveFileDialog dlg = new SaveFileDialog()) {
if (dlg.ShowDialog() == DialogResult.OK) {
string fileName = dlg.FileName;
SaveToFile(fileName);
}
}
}
private void SaveToFile(string fileName) {
System.IO.TextWriter w = new System.IO.StreamWriter(fileName);
w.Write(sb.ToString());
w.Flush();
w.Close();
}
}
StringBuilder.ToString() will get you the string.
This link will show you how to write text to a file.
This link will show you how to call SaveFileDialog and pass a stream to it to save.
Hope that helps.
StringBuilder.ToString() can be passed to the TextStream.Write() method after creating the file.
Using the SaveFileDialog class, you can let the user select path and file name - in a standard way. Detailed examples in the doc.

Resources