I have a WPF Application which contains a class called RateView.xaml.cs and MainWindow.xaml.cs
The MainWindow.xaml.cs contains three textboxes of which values I want to pass into the RateView.xaml.cs. The content of these textboxes can be changed by the end user but regardless of that I always want whatever the value is of the textbox to be going into rateview.xaml.cs.
How can this be done?
I am a newbie to coding hence not sure, someone mentioned Get and Set statements, if so how can I do these?
Currently I access my textboxes like this in the MainWindow:
private float GetSomeNumber()
{
bool Number1 = false;
float parsedNumber1Value = 0.00F;
Number1 = float.TryParse(Number1_TextBox.Text, out parsedNumber1Value);
return parsedNumber1Value;
}
The GetSomeNumber() method is then passed to another seperate class to do some calculation with.
On intital load it works of the value from my method, but once someone changes the value rateview.xaml.cs doesn't recognise this change and always uses the values that were first loaded.
Thanks
Just a small example (This is winforms)
This is the mainwindow, where your textbox is:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
1
public string TextBox1Text
{
get { return textBox1.Text; }
set { textBox1.Text = value;
}
}
and this is a class where you want to interact with the textboxes:
public class Test
{
public Test(Form1 form)
{
//Set the text of the textbox in the form1
form.TextBox1Text = "Hello World";
}
}
To get and set the value of a textbox within another class/form you can do it with something like:
public string TextBox1Text
{ get { return textBox1.Text; }
set { textBox1.Text = value; } }
Related
I am very new to WPF and couldn't get my head around this so checked couple tutorials and kinda merged them together and I am here with this mess. Dont really know how should I describe my issue around so I decided to write here.
What I am working on;
Using a WPF I got a menu opening UserControls inside the Main Window.
When Main Window starts I am starting a thread like this so I get a loop
private void MainLoop()
{
Thread th = Thread.CurrentThread;
while (th.ThreadState != ThreadState.AbortRequested &&
th.ThreadState != ThreadState.Aborted)
{
if (bMainOk)
{
switch (activeUC)
{
case "ucDurum":
LoopControl.ucDurumLoop(plc, connectionString);
break;
case "ucAyarlar":
//LoopControl.ucAyarlarLoop();
break;
default:
break;
}
}
Thread.Sleep(2000);
}
}
That LoopControl class has functions inside that are looping depending on the active UserControl.
public class LoopControl : ObservableObject
{
public static void ucDurumLoop(ActUtlType plc, string connectionString)
{
DurumVM durum = new DurumVM();
// The values do change before this lines, I didnt put them for the sake of clarity
durum.RaporAktif = "true";
durum.RaporAdedi = arrayData[0].ToString();
durum.BufferPercent = "%" + (float)arrayData[0] / 250 * 100;
durum.PlcSonCounter = arrayData[4].ToString();
durum.SqlSonCounter = sonCntr.ToString();
}
}
Which is Connected to a Main ViewModel then sub ViewModels like so
class MainVM
{
public DurumVM Durum { get; private set; }
public AyarlarVM Ayarlar { get; private set; }
public MainVM()
{
Durum = new DurumVM();
Ayarlar = new AyarlarVM();
}
}
public class DurumVM : ObservableObject
{
#region PLCVars
private bool _raporAktif;
private string _raporAdedi;
private string _bufferPercent;
private string _plcSonCounter;
private string _sqlSonCounter;
#endregion
#region PLCGetSets
public string RaporAktif
{
get
{
if (_raporAktif)
return "Düzenlenecek True";
return "Düzenlenecek False";
}
set
{
_raporAktif = Convert.ToBoolean(value);
OnPropertyChanged("RaporAktif");
}
}
public string RaporAdedi
{
get
{
if (string.IsNullOrEmpty(_raporAdedi))
return "Zeroh";
return _raporAdedi;
}
set
{
_raporAdedi = value;
OnPropertyChanged("RaporAdedi");
}
}
public string BufferPercent
{
get
{
if (string.IsNullOrEmpty(_bufferPercent))
return "%0";
return _bufferPercent;
}
set
{
_bufferPercent = (value.Length <= 5 ? value : value.Substring(0, 5));
OnPropertyChanged("BufferPercent");
}
}
public string PlcSonCounter
{
get
{
if (string.IsNullOrEmpty(_plcSonCounter))
return "0";
return _plcSonCounter;
}
set
{
_plcSonCounter = value;
OnPropertyChanged("PlcSonCounter");
}
}
public string SqlSonCounter
{
get
{
if (string.IsNullOrEmpty(_sqlSonCounter))
return "0";
return _sqlSonCounter;
}
set
{
_sqlSonCounter = value;
OnPropertyChanged("SqlSonCounter");
}
}
#endregion
}
And the user control are bound to these values:
<StackPanel>
<DockPanel>
<Label Content="Aktif mi? :" VerticalAlignment="Center"/>
<TextBlock Text="{Binding RaporAktif, UpdateSourceTrigger=PropertyChanged}" DockPanel.Dock="Right" Margin="0,0,25,0" HorizontalAlignment="Right" VerticalAlignment="Center">
<TextBlock.Effect>
<DropShadowEffect/>
</TextBlock.Effect>
</TextBlock>
</DockPanel>
...
public partial class ucDurum : UserControl
{
MainVM viewModel = new MainVM();
//LoopControl viewModel = new LoopControl();
public ucDurum()
{
InitializeComponent();
this.DataContext = viewModel.Durum;
Control.activeUC = "ucDurum";
}
}
Quick sum:
I got set of user controls and one main loop. Main loop has parts that only works if correct user control is active, connects to somewhere else and gets values then sets these values on a reference, sends it to user control and textblocks the values bound will update
What is wrong that I know:
Practice might be very incorrect. It was looking good in my head but I realized the problem. Mainly due to my lack of C# knowledge. The main loop gets reference of VM sets the datas but never sends them anywhere as I bolded in quick summary. I certain the problem is there since the values I got are correct, when I change values view button etc they do change and update. But VM has no idea about LoopControl.
In MVC I'd return the referenced object then get values on view. In here the values are bound directly and I am kind of lost.
Thanks in advance.
Update:
I'm sorry I wasn't clear enough above the last paragraphs.
What I expect it to do:
LoopControl.ucDurumLoop updates DurumVM using referenced object so the user control "ucDurum" can see it and update TextBlock values accordingly.
What is happening:
I set up the referenced object in LoopControl.ucDurumLoop with the values but that is just an object and stays there. Doesn't go to DurumVM and update values using their Get/Set 's, so values are same and user control "ucDurum" has no idea what is going on on LoopControl.
Well I was being stupid.
Problem was, I was creating new object reference and updating it while I had to reference the one on UserControl.
All I needed was changing a line in LoopControl
public class LoopControl : ObservableObject
{
public static void ucDurumLoop(ActUtlType plc, string connectionString)
{
DurumVM durum = new DurumVM(); // Changing this
DurumVM durum = ucDurum.viewModel; // To this.
durum.RaporAktif = "true";
durum.RaporAdedi = arrayData[0].ToString();
durum.BufferPercent = "%" + (float)arrayData[0] / 250 * 100;
durum.PlcSonCounter = arrayData[4].ToString();
durum.SqlSonCounter = sonCntr.ToString();
}
}
I have a winform called Form1 and a textbox called textBox1
In the Form1 I can set the text by typing:
textBox1.text = "change text";
Now I have created another class. How do I call textBox1 in this class?
so I want to change the text for textBox1 in this class.
How can I access the Form1 from this new class?
I would recommend that you don't. Do you really want to have a class that is dependent on how the text editing is implemented in the form, or do you want a mechanism allowing you to get and set the text?
I would suggest the latter. So in your form, create a property that wraps the Text property of the TextBox control in question:
public string FirstName
{
get { return firstNameTextBox.Text; }
set { firstNameTextBox.Text = value; }
}
Next, create some mechanism through which you class can get a reference to the form (through the contructor for instance). Then that class can use the property to access and modify the text:
class SomeClass
{
private readonly YourFormClass form;
public SomeClass(YourFormClass form)
{
this.form = form;
}
private void SomeMethodDoingStuffWithText()
{
string firstName = form.FirstName;
form.FirstName = "some name";
}
}
An even better solution would be to define the possible interactions in an interface, and let that interface be the contract between your form and the other class. That way the class is completely decoupled from the form, and can use anyting implementing the interface (which opens the door for far easier testing):
interface IYourForm
{
string FirstName { get; set; }
}
In your form class:
class YourFormClass : Form, IYourForm
{
// lots of other code here
public string FirstName
{
get { return firstNameTextBox.Text; }
set { firstNameTextBox.Text = value; }
}
}
...and the class:
class SomeClass
{
private readonly IYourForm form;
public SomeClass(IYourForm form)
{
this.form = form;
}
// and so on
}
I was also facing the same problem where I was not able to appendText to richTextBox of Form class. So I created a method called update, where I used to pass a message from Class1.
class: Form1.cs
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
_Form1 = this;
}
public static Form1 _Form1;
public void update(string message)
{
textBox1.Text = message;
}
private void Form1_Load(object sender, EventArgs e)
{
Class1 sample = new Class1();
}
}
class: Class1.cs
public class Class1
{
public Class1()
{
Form1._Form1.update("change text");
}
}
You can change the access modifier for the generated field in Form1.Designer.cs from private to public. Change this
private System.Windows.Forms.TextBox textBox1;
by this
public System.Windows.Forms.TextBox textBox1;
You can now handle it using a reference of the form Form1.textBox1.
Visual Studio will not overwrite this if you make any changes to the control properties, unless you delete it and recreate it.
You can also chane it from the UI if you are not confortable with editing code directly. Look for the Modifiers property:
public partial class Form1 : Form
{
public static Form1 gui;
public Form1()
{
InitializeComponent();
gui = this;
}
public void WriteLog(string log)
{
this.Invoke(new Action(() => { txtbx_test1.Text += log; }));
}
}
public class SomeAnotherClass
{
public void Test()
{
Form1.gui.WriteLog("1234");
}
}
I like this solution.
You will need to have some access to the Form's Instance to access its Controls collection and thereby changing the Text Box's Text.
One of ways could be that You can have a Your Form's Instance Available as Public or More better Create a new Constructor For your Second Form and have it receive the Form1's instance during initialization.
Define a property of the form like, then use this in other places it would be available with the form instance
public string SetText
{
get { return textBox1.Text; }
set { textBox1.Text = value; }
}
If your other class inherits Form1 and if your textBox1 is declared public, then you can access that text box from your other class by simply calling:
otherClassInstance.textBox1.Text = "hello world";
Use, a global variable or property for assigning the value to the textbox, give the value for the variable in another class and assign it to the textbox.text in form class.
I Found an easy way to do this,I've tested it,it works Properly.
First I created a Windows Project,on the form I Inserted a TextBox and I named it textBox1
then I inserted a button named button1,then add a class named class1.
in the class1 I created a TextBox:
class class1
{
public static TextBox txt1=new TextBox(); //a global textbox to interfece with form1
public static void Hello()
{
txt1.Text="Hello";
}
}
Now in your Form Do this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
class1.txt1=textBox1;
class1.Hello();
}
}
in the button1_Click I coppied the object textBox1 into txt1,so now txt1 has the properties
of textBox1 and u can change textBox1 text in another form or class.
Form1 form = new Form1();
form.textBox1.Text = "test";
I tried the examples above, but none worked as described. However, I have a solution that is combined from some of the examples:
public static Form1 gui;
public Form1()
{
InitializeComponent();
gui = this;
comms = new Comms();
}
public Comms()
{
Form1.gui.tsStatus.Text = "test";
Form1.gui.addLogLine("Hello from Comms class");
Form1.gui.bn_connect.Text = "Comms";
}
This works so long as you're not using threads. Using threads would require more code and was not needed for my task.
I used this method for updating a label but you could easily change it to a textbox:
Class:
public Class1
{
public Form_Class formToOutput;
public Class1(Form_Class f){
formToOutput = f;
}
// Then call this method and pass whatever string
private void Write(string s)
{
formToOutput.MethodToBeCalledByClass(s);
}
}
Form methods that will do the updating:
public Form_Class{
// Methods that will do the updating
public void MethodToBeCalledByClass(string messageToSend)
{
if (InvokeRequired) {
Invoke(new OutputDelegate(UpdateText),messageToSend);
}
}
public delegate void OutputDelegate(string messageToSend);
public void UpdateText(string messageToSend)
{
label1.Text = messageToSend;
}
}
Finally
Just pass the form through the constructor:
Class1 c = new Class1(this);
Form frm1 = new Form1();
frm1.Controls.Find("control_name",true)[0].Text = "I changed this from another form";
// Take the Active form to a form variable.
Form F1 = myForm1.ActiveForm;
//Findout the Conntrol and Change the properties
F1.Controls.Find("Textbox1", true).ElementAt(0).Text= "Whatever you want to write";
What about
Form1.textBox1.text = "change text";
note:
1. you have to "include" Form1 to your second form source file by
using Form1;
textBox1 should be public
On load of a new Window I add a dynamic number of UserControls (SetInformation) to my window as below
public Window_NewWorkoutLine(int NoOfSets, int workoutLineId)
{
InitializeComponent();
currentWorkoutLineId = workoutLineId;
for (int x = 1; x <= NoOfSets; x++)
{
SetInformation setInformation = new SetInformation(x);
StackPanel_Main.Children.Add(setInformation);
}
}
Each of the UserControls contains 2 textboxes, what I need to do is grab the Text property from each textbox on each UserControl and use them in an insert query to a database. The data from each UserControl will be added to a seperate row in the database.
Any ideas guys?
Thanks in advance
I think you could enumerate all UIElement or "StackPanel_Main", and then cast them.
For example (with use of System.Linq) :
foreach (SetInformation setInformation in StackPanel_Main.Children.OfType<SetInformation>())
{
string txt1 = setInformation.Text1;
string txt2 = setInformation.Text2;
}
But I think this would be better to associate a "Value Object" to each instance of your UserControl to separate User Interface (UI) from Data. You could do that with Binding for example.
First declare your class which will contain your data with implementation of INotifyPropertyChanged for UI integration :
/// <summary>
/// This objet contains all useful data
/// </summary>
public class InformationValueObject : INotifyPropertyChanged
{
private string _text1;
private string _text2;
public string Text1
{
get { return _text1; }
set { _text1 = value; OnPropertyChanged("Text1"); }
}
public string Text2
{
get { return _text2; }
set { _text2 = value; OnPropertyChanged("Text2"); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Then add Binding to your UserControl, as you like, for example you could just set the DataContext of your UserControl like bellow, and then Bind each property to each TextBox from DataContext :
public partial class Window_NewWorkoutLine : Window
{
private List<InformationValueObject> _valueObjects = new List<InformationValueObject>();
public Window_NewWorkoutLine(int NoOfSets, int workoutLineId)
{
InitializeComponent();
currentWorkoutLineId = workoutLineId;
for (int x = 1; x <= NoOfSets; x++)
{
SetInformation setInformation = new SetInformation(x);
InformationValueObject vo = new InformationValueObject();
setInformation.DataContext = _vo;
_valueObjects.Add(vo);
StackPanel_Main.Children.Add(setInformation);
}
}
}
It is then easy to retrieve values by reading private collection "_valueObjects". No more need to enumerate User Interface composition.
It is really important to separate data and display.
My example could also be improved a lot.
For example, a ListView is composed (by default) by a StackPanel inside a ScrollViewer, and you can set the "ItemsSource" property with _valueObjects collection, and customize Item template to use your custom UserControl.
Then you can improve again by using a MVVM model with the Binding of your collection onto your ListBox. You could also use an ObservableCollection<InformationValueObject> instead of a List<InformationValueObject> if you want to be able to add or remove items dynamically...
I know this is not possible to masterize everything, but I think it could be great to tend to these solutions by separating data and visualization.
Best regards,
Maybe try adding a public property to your control to get and set text to the text boxes:
public string Text
{
get
{
return txtTextBox.Text.ToString();
}
set
{
txtTextBox.Text = HttpUtility.HtmlDecode(value);
}
}
You can add accessors to the user controls:
public class SetInformation{
private TextBox box1;
private TextBox box2;
public string Box1Text{
get{
return box1.Text;
}
}
public string Box2Text{
get{
return box2.Text;
}
}
...
...
}
For example, in same class I'm using "this" word. But how can I access to THIS RichTextBox from another class.
private void deleteSymbol_Click(object sender, EventArgs e)
{
string text = this.dataTextBox.Text;
this.dataTextBox.Text = text.Remove(0, 1);
}
Examples below are not working.
MainForm mf = new MainForm();
mf.dataTextBox.Text = text.Remove(0, 1);
or
MainForm mf;
mf.dataTextBox.Text = text.Remove(0, 1);
doesn't works.
Try this,
In your main form;
public MainForm()
{
InitializeComponent();
main = this;
}
internal static MainForm main;
internal string Status
{
get { return dataTextBox.Text.ToString(); }
set { dataTextBox.Text = value; }
}
From your calling class,
MainForm.main.Status = "Your message";
:)
First of all you should change the Modifiers property of your richtextbox control to public or some other accessible options to allow other classes identify your control. then your codes would work.
Instead of changing your richtextbox to public, I would suggest implementing public properties on your mainform. Call these specific properties to do some work for you on the mainform's richtextbox...
Public property in your mainform:
Private newRTBtext As String
Public Property RTBtext() As String
Get
Return RichTextBox1.Text
End Get
Set(ByVal value As String)
newRTBtext = value
RichTextBox1.Text = value
End Set
End Property
Call this property on mainform to set or get text in your richtextbox... this is an example property, create the properties and methods you need.
this is not long story!! just it seems to be long ;)
in my app I have user access, it means access to a button relate to its user access scope.
in winform layer: I have a form, it shows all of the determined buttons' name in partitioned checkedListboxes. I dont want fill the form manually. I want create checkedListboxes by code. to get their items'text, I have below planing:
clssMenu_Item: I can save name and text property of one button in this class.
public class clssMenu_Item
{
public string name;
public string text;
}
clssMenu_List: it give me 2D generic List<clssMenu_Item>. all of the buttons in one form will be in a object of this class.
public class clssMenu_List
{
public clssMenu_List ()
{
// I dont know how fill private variables
}
#region private variables
private List<clssMenu_Item> _main ; // buttons in main form
private List<clssMenu_Item> _accountancy; //buttons in accountancy form
private List<clssMenu_Item> _management; //buttons in management form
#endregion
#region public properties
public List<clssMenu_Item> main
{ get { return _main; } }
public List<clssMenu_Item> accountancy
{ get { return _accountancy; } }
public List<clssMenu_Item> management
{ get { return _management; } }
#endregion
}
the buttons in each forms have a common character in their Name property. For example all of the determined buttons in Main form are started with ''Mbtn'', so there isn't any same buttons' Name between forms.
now I dont know how fill private variables in clssMenu_List. then I could use it in my facade layer.
thanks for your attention my friend!! please help me to solve it
I would create a separated helper class that extracts all buttons from a form.
public static class FormHelper
{
public static Button[] GetButtonsFromForm(Form form)
{
// ...
}
}
I would create properties instead of fields:
public class clssMenu_Item
{
public string Name {get;set;}
public string Text {get;set;}
}
A method to create menu_items:
public IEnumerable<clssMenu_Item> GetMenuItemsFromForm(Form form)
{
// convert the buttons to menu_items
return from button in FormHelper.GetButtonsFromForm(form);
select new clssMenu_Item { Name = button.Name, Text = button.Text };
}
Next I would add all buttons to the right list.
public void Fill()
{
clssMenu_List lst = new clssMenu_List();
clssMenu_List.main.AddRange(GetMenuItemsFromForm(mainForm));
clssMenu_List.accountancy.AddRange(GetMenuItemsFromForm(accountancyForm));
clssMenu_List.management.AddRange(GetMenuItemsFromForm(managementForm));
}
Don't forget to create the list in you class:
private List<clssMenu_Item> _main = new List<classMenu_Item>(); // buttons in main form
private List<clssMenu_Item> _accountancy = new List<classMenu_Item>(); //buttons in accountancy form
private List<clssMenu_Item> _management = new List<classMenu_Item>(); //buttons in management form
Personally:
I would store them in a dictionary because you can access them by name. And I would not create properties of List-types. I'd rather create Add/Remove methods.