Having some real trouble understanding where I've gone wrong here. I've marked in the code what and where. I am using an XAML interface and do have objects for everything here. The code compiles but the TextBlock will not update with the result from updateVTCShortCode Thanks for the help!
MAIN PROGRAM
namespace VTCPT
{
/// <summary>
///
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
public void shortFormCodec_SelectionChanged(object sender, RoutedEventArgs e)
{
//UPDATE THE SHORTCODE TEXTBLOCK
updateVTCShortCode display = new updateVTCShortCode();
display.mergeShortCode(longFormCodec.SelectedItem.ToString());
if (String.IsNullOrEmpty(display.finalResult()))
{ shortFormCodec.Text = ".."; }
else { shortFormCodec.Text = display.finalResult();
shortFormCodec.Text = "test";
} /////THIS IS NOT ACTUALLY GETTING A RETURN
}
public void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
private void updateShortForm(object sender, SelectionChangedEventArgs e)
{
}
private void TextBlock_SelectionChanged(object sender, RoutedEventArgs e)
{
}
private void fsSiteBuild_SelectionChanged(object sender, RoutedEventArgs e)
{
}
private void updateSiteBuild(object sender, TextChangedEventArgs e)
{
int index = fsRoomDesig.Text.IndexOf(".");
if (index > 0)
{ fsSiteBuild.Text = fsRoomDesig.Text.Substring(0, index); }
else { fsSiteBuild.Text = ".."; }
}
private void vtcSystemName_SelectionChanged(object sender, RoutedEventArgs e)
{
}
}
}
updateVTCShortCode CLASS
namespace VTCPT
{
class updateVTCShortCode
{
String result = "";
public void mergeShortCode(String longFormCodec)
{ if (longFormCodec.Equals("Cisco SX80"))
{
String sendShortForm = "SX80";
result = "V-T" + sendShortForm;
}
if (longFormCodec.Equals("Cisco Webex Codec Plus"))
{
String sendShortForm = "SRK";
result = "V-T" + sendShortForm;
}
if (longFormCodec.Equals("Cisco Webex Codec Pro"))
{
String sendShortForm = "SRK";
result = "V-T" + sendShortForm;
}
}
public String finalResult()
{ return result; } //////SHOULD BE GETTING SENT BACK TO MAIN PROGRAM
}
}
I think the problem is that in the following code taken from your shortFormCodec_SelectionChanged method. You set shortFormCodec.Text = display.finalResult(); immediately followed by shortFormCodec.Text = "test";. The final result will never be visible because it is being immediately overwritten with "test".
if (String.IsNullOrEmpty(display.finalResult()))
{
shortFormCodec.Text = "..";
}
else
{
shortFormCodec.Text = display.finalResult();
shortFormCodec.Text = "test";
}
As TheGeneral suggested in the comments, you should be able to identify this using breakpoints and stepping through the code (using the F8 key) while watching the values of your variables and text fields. If you hover your mouse over the variables and the .Text section of any shortFormCodec.Text line it will show you its value at that point in the program.
However, I think you may find it helpful if you adjust your code to use an if {} else if {} else {} structure. I would also change the finalResult() method to a property as it's doing nothing but return a string. For example:
class updateVTCShortCode
{
// You could set the default value to an empty string I.e. = ""
// but having it set to "Not set" may help you spot any problems for now.
// As long as you remember to call mergeShortCode() first, you would never
// see "Not set" returned anyway. But this would help you spot that mistake.
public string FinalResult { get; set; } = "Not set";
public void mergeShortCode(String longFormCodec)
{
if (longFormCodec.Equals("Cisco SX80"))
{
String sendShortForm = "SX80";
FinalResult = "V-T" + sendShortForm;
}
else if (longFormCodec.Equals("Cisco Webex Codec Plus"))
{
String sendShortForm = "SRK";
FinalResult = "V-T" + sendShortForm;
}
else if (longFormCodec.Equals("Cisco Webex Codec Pro"))
{
String sendShortForm = "SRK";
FinalResult = "V-T" + sendShortForm;
} else
{
// If longFormCodec is not matched, set the result to ".."
FinalResult = "..";
}
}
By setting the final result to ".." in the else block of the mergeShortCode() method and setting a default value for the FinalResult property (even if it is an empty string I.e. ""). You are preventing FinalResult ever being null and providing all possible outcomes from the one function. This means you can simplify the shortFormCodec_SelectionChanged() method to the following and easily reuse the mergeShortCode() method elsewhere:
public void shortFormCodec_SelectionChanged(object sender, RoutedEventArgs e)
{
//UPDATE THE SHORTCODE TEXTBLOCK
updateVTCShortCode display = new updateVTCShortCode();
display.mergeShortCode(longFormCodec.SelectedItem.ToString());
shortFormCodec.Text = display.FinalResult;
}
}
Related
I'm new to C# and I can't figure out how to reference the value of a variable from one class to another.
It's set to when the button is pressed, it'll take the text in the text box and sets that as "alphaask". Then it instances "alphaanswer" which would tell the label to change its text.
"alphaanswer" will take the value "alphaQuest" and see if its equal to "bob" which then would change the label.
ALL I want to know how to set the value of "alphaQuest" from the value of "alphaask" so the string can check it with "alphaanswer"
public partial class QuestionTab : Form
{
public string alphaask = "null";
public void button1_Click(object sender, EventArgs e)
{
// alphabutton
// Checks if something is in textbox then says bool is true
bool asked = false;
if(textBoxAlpha.Text != "")
{
alphaask = textBoxAlpha.Text;
asked = true;
}
if(asked==true)
{
// If bool is true than instance auxy
var instance = new Alpha();
instance.alphaanswer();
}
}
}
public class Alpha
{
string alphaQuest = // <-- I want to make alphaQuest equal to alphaask
alphaanswer();
public void alphaanswer()
{
if (alphaanswer == bob)
{
//change text in label1
}
}
}
Do these changes
public partial class QuestionTab : Form
{
public string alphaask = "null";
public void button1_Click(object sender, EventArgs e)
{
bool asked = false;
if(textBoxAlpha.Text != "")
{
alphaask = textBoxAlpha.Text;
asked = true;
}
if(asked==true)
{
// If bool is true than instance auxy
var instance = new Alpha();
instance.alphaAnswer(alphaask);
//Here you are sending the current value of alphaAsk to the alphaanswer method.
}
}
}
public class Alpha
{
public void alphaAnswer(string alphaAnswer) //This string receives the value you sent
{
if (alphaAnswer == "bob")
{
//change text in label1
}
}
}
make a contractor in class Alpha with String parameter
public Alpha(String value)
{
}
then when you call it
var instance = new Alpha(alphaask);
instance.show();
I am currently writing an application in WPF C# that is some kind of helper for other processes which are written in Java. Those other processes require a configuration.csv in which different "names" are listed with a column that says "SKIP". If the column is X at Skip, my java program will skip those names and therefore their dependent processes.
If I open the CSV with Excel and edit the rows, everything works perfectly fine. That's not the problem. What I want to achieve is to list the rows into a DataGrid in a WPF App (except the first and last row), where the user can tick a checkbox to decide if he wants to skip that specific name or not. By pressing Save, the .CSV gets updated.
I already wrote some code with a friend who's more familiar with this topic. It worked fine in WinForms but doesn't work on WPF. We are not able to get the values of the checkboxes and not able to save them into the CSV.
CODE:
private void OBJ_SaveButton_Click(object sender, RoutedEventArgs e)
{
if (OBJ_DataGrid.Items.Count == 0)
{
MessageBox.Show("Kein Datensatz in der View.");
return;
}
/*if (Directory.Exists(path))
{
if (File.Exists(filepath))
{
string tmp = null;
try
{
FileStream fileStr = new FileStream(filepath, FileMode.Create);
StreamWriter strWriter = new StreamWriter(fileStr);
strWriter.WriteLine("SFObject;Skip");
for(int i=0;i< itmGrd.Count;i++)
{
switch (itmGrd[i].ItemValue)
{
case true:
tmp = itmGrd[i].ItemName + ";X";
break;
case false:
tmp = itmGrd[i].ItemName + ";";
break;
}
strWriter.WriteLine(tmp);
}
strWriter.WriteLine("SuccessMSG;");
strWriter.Close();
fileStr.Close();
LoadConf();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
else
MessageBox.Show("ERR_F0: Pfad nicht gefunden.");
}
else
MessageBox.Show("ERR_D0: Pfad nicht gefunden.");*/
}
private void OBJ_ReloadButton_Click(object sender, RoutedEventArgs e)
{
}
private void OBJ_DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
private void OBJ_DataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
MessageBox.Show(e.Row.ToString());
}
void OnChecked(object sender, RoutedEventArgs e)
{
MessageBox.Show(e.Source.ToString());
}
}
public class ItemGrid
{
public ItemGrid(string name, bool rval)
{
ItemName = name;
ItemValue = rval;
}
public string ItemName { set; get; }
public bool ItemValue { set; get; }
}
public class ItemsGrid : List<ItemGrid>
{
public string path = null;
public string filepath = null;
public ItemsGrid()
{
path = String.Format(#"{0}\build\", Environment.CurrentDirectory);
filepath = Path.Combine(path + "configuration.csv");
if (Directory.Exists(path))
{
if (File.Exists(filepath))
{
string line = null;
StreamReader file = new StreamReader(filepath);
while ((line = file.ReadLine()) != null)
{
if (!line.Equals("SFObject;Skip") && !line.Equals("SuccessMSG;"))
{
string input = (line.IndexOf(";X") != -1 ? (line.Replace(";X", "")) : (line.Replace(";", "")));
Add(new ItemGrid(input, (line.IndexOf(";X") != -1 ? (true) : (false))));
}
}
file.Close();
}
else
MessageBox.Show("ERR_F0: Pfad nicht gefunden.");
}
else
MessageBox.Show("ERR_D0: Pfad nicht gefunden.");
//Add(new ItemGrid("Tom", false));
// Add(new ItemGrid("Jen", false));
}
}
This is how it looks (and should look like).
CSV:
I hope that you guys can help me out, I really don't understand why it's not working. I also have to admit that I am not any near of being proficient in C#.
I'm assuming the CSV you pasted is considered properly formatted.
// HelperClass.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WpfCsvSkipTicker
{
public static class HelperClass
{
public static List<ItemGrid> ReadCsv(string filepath)
{
if (!File.Exists(filepath)) return null;
var allLines = File.ReadAllLines(filepath);
var result =
from line in allLines.Skip(1).Take(allLines.Length -2)
let temparry = line.Split(';')
let isSkip =
temparry.Length > 1
&& temparry[1] != null
&& temparry[1] == "X"
select new ItemGrid { ItemName = temparry[0], ItemValue = !isSkip };
return result.ToList();
}
public static void WriteCsv(IEnumerable<ItemGrid> items, string filepath)
{
var temparray = items.Select(item => item.ItemName + ";" + (item.ItemValue ? "" : "X")).ToArray();
var contents = new string[temparray.Length + 2];
Array.Copy(temparray, 0, contents, 1, temparray.Length);
contents[0] = "SFOBject;Skip";
contents[contents.Length - 1] = "SuccessMSG;";
File.WriteAllLines(filepath, contents);
}
}
public class ItemGrid
{
public string ItemName { set; get; }
public bool ItemValue { set; get; }
}
}
And...
// MainWindow.xaml.cs
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.dataGridView.ItemsSource = HelperClass.ReadCsv(#"PathToRead\configuration.csv");
}
private void btnSave_Click(object sender, RoutedEventArgs e)
{
var temp = new List<ItemGrid>();
for (int i = 0; i < this.dataGridView.Items.Count; i++)
{
if (this.dataGridView.Items[i] is ItemGrid) // DataGrid pads it's item collection with elements we didn't add.
temp.Add((ItemGrid)this.dataGridView.Items[i]);
}
HelperClass.WriteCsv(temp, #"PathToSave\new_configuration.csv");
}
}
I have this short windows form application code that i cannot get to work properly. It uses an instance of a class (as a temporary storage place) to populate an array of the same class type. It has a button and a textbox. If you press the button, the text is saved in the Name member and added to the array.
If the Name is taken by another array member, it should show a message "name taken!" and not add it to the array. The problem is that this condition check is always true!
if we type in "Marry", the debugger shows that
if (examleArray[i].Name == temp.Name)
is equivalent to:
if ("Marry" == "Marry")
as if one is pointing to the other. Why is this? how do i fix it? thank you!
namespace errorexample
{
public partial class Form1 : Form
{
example temp = new example();
example[] examleArray = new example[10];
int examleArrayIndex = 0;
bool NameTaken = false;
public Form1()
{ InitializeComponent(); }
private void button1_Click(object sender, EventArgs e)
{
temp.Name = textBox1.Text;
NameTaken = false;
for (var i = 0; i < (examleArrayIndex); i++)
{
if (examleArray[i].Name == temp.Name)
{
NameTaken = true;
MessageBox.Show("Name taken!");
}
}
if (NameTaken == false)
{
examleArray[examleArrayIndex] = temp;
examleArrayIndex++;
}
}
}
public class example {
public string Name;
}
}
You only have one temp object, and you add keep adding it to the array. It's the same temp since you never create a new one. I've rewritten it for you:
List<example> examleArray = new List<example>();
private void button1_Click(object sender, EventArgs e)
{
if (examleArray.Any(e=>e.Name == textBox1.Text))
{
MessageBox.Show("Name taken!");
} else {
examleArray.Add(new example { Name = textBox1.Text });
}
}
I've also converted your fixed array into a List so you don't ever accidentally try and add 11 names and then blow up. And I've converted your search to LINQ to simplify.
You only create one example object. You are putting multiple references to the same object into the array. One solution is to create a new example object to put in the array:
public class example {
public string Name;
public example( string name ){
Name = name;
}
}
//...
examleArray[examleArrayIndex] = new example( temp.Name );
move temp object initialization inside the click event, otherwise you are updating same object
private void button1_Click(object sender, EventArgs e)
{
example temp = new example();
temp.Name = textBox1.Text;
NameTaken = false;
for (var i = 0; i < (examleArrayIndex); i++)
{
if (examleArray[i].Name == temp.Name)
{
NameTaken = true;
MessageBox.Show("Name taken!");
}
}
if (NameTaken == false)
{
examleArray[examleArrayIndex] = temp;
examleArrayIndex++;
}
}
you can use List
List<string> example =
new List<string>();
if(example.Contains(textBox1.Text))
{
MessageBox.Show("Name taken!");
}else
{
example.Add(textBox1.Text);
}
I wish to add a search function to my application, I've seen many examples however, all of the data is added by the programmer. How would I implement a search function where the parameters/values aren't pre-defined. I'm guessing I'd have to create another instance of a List<> as I'm already using one?
public Form1()
{
InitializeComponent();
}
List<Book> books = new List<Book>();
private void Form1_Load(object sender, EventArgs e)
{
}
//Settng Values
public void button1_Click(object sender, EventArgs e)
{
Book b = new Book();
b.Title = textBox1.Text;
b.ISBN = textBox2.Text;
b.Onloan = trueCheckBox.Checked;
listView1.Items.Add(b.Title + ", " + b.ISBN + ", " + b.Onloan);
books.Add(b);
textBox1.Text = null;
textBox2.Text = null;
}
//Method to check if item is aviable or note - boolean type
void avaiable()
{
if (trueCheckBox.Checked = true)
{
bool onloan = true;
}
else
{
bool onloan = false;
}
}
private void button2_Click(object sender, EventArgs e)
{
Remove();
}
//Remove item from both the List & Listview
void Remove()
{
try
{
listView1.Items.Remove(listView1.SelectedItems[0]);
books.RemoveAt(listView1.SelectedItems[0].Index);
}
catch
{
}
}
//Display information within their field when selected an item is selected
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
if (listView1.SelectedItems.Count == 0)
{
return;
}
else
{
textBox1.Text = books[listView1.SelectedItems[0].Index].Title;
textBox2.Text = books[listView1.SelectedItems[0].Index].ISBN;
trueCheckBox.Checked = books[listView1.SelectedItems[0].Index].Onloan;
}
}
//Update the values without having to re-add
private void button3_Click(object sender, EventArgs e)
{
if (listView1.SelectedItems.Count == 0)
{
return;
}
else
{
books[listView1.SelectedItems[0].Index].Title = textBox1.Text;
books[listView1.SelectedItems[0].Index].ISBN = textBox2.Text;
books[listView1.SelectedItems[0].Index].Onloan = trueCheckBox.Checked;
listView1.SelectedItems[0].Text = textBox1.Text + ", " + textBox2.Text + ", "+ trueCheckBox.Checked;
}
}
private void searchBox_TextChanged(object sender, EventArgs e)
{
//Here's where I am stuck, I've added a textField and labelled it search box
}
}
//Class - set & get methods
class Book
{
public string isbn;
public string title;
private Boolean onloan;
public Book()
{
this.isbn = isbn;
this.title = title;
}
public string ISBN
{
get { return isbn; }
set { isbn = value; }
}
public string Title
{
get { return title; }
set { title = value; }
}
public Boolean Onloan
{
get { return onloan; }
set { onloan = value; }
}
}
}
Thank you.
EDIT-
Essentially, the search function should allow the user to search for a book using just a substring i.e. "Mars" should return a the book with the title "The Programmer From Mars" < (Just an example). I'm guessing I'd have to use the .Contain method?
Correct, you will need to use the "Contains" method. Note that "Contains" is case sensitive so you would need to cater for that.
So you would have something like:
var textToSearch = searchBox.Text.ToLower();
var foundBooks = books.Where(book => book.Title.ToLower().Contains(textToSearch)).ToList();
Assuming books is the list of books to search from:
List<Book> searchResult = books.Where(b => b.Title.Contains(searchTerm)).ToList();
This would return a list of books where the input string is found in the title.
You can do exact matching with b.Title == searchTerm, and similar with the other properties of Book.
The syntax above is LINQ and can be a little confusing at first, but works very well for things like this.
Edit:
To use this, you'll want using System.Linq;
Since your search seems to be on TextChanged, you'd want to put this code in your searchBox_TextChanged() method:
This gets the textbox the user is typing into:
TextBox searchTerm = sender as TextBox;
And this filters your list of books by the current search:
List<Book> searchResult = books.Where(b => b.Title.Contains(searchTerm.Text)).ToList();
Note as in the other answer you may want to do ToLower() (or upper) to make searches case-insensitive.
All that's left to do now is display the filtered result searchResult back to the user.
Managed to do it, this is my code and it works. If anyone wants to use it for future reference here it is.
private void button4_Click(object sender, EventArgs e)
{
listView1.SelectedItems.Clear();
for (int i = listView1.Items.Count -1; i >= 0; i--)
{
if (listView1.Items[i].ToString().ToLower().Contains(searchBox.Text.ToLower())) {
listView1.Items[i].Selected = true;
}
}
This is my class :
class Discussion
{
public String name {get; set;}
public String discussionId { get; set; }
public List<Message> liste {get; set;}
public Discussion(String name, String discussionId)
{
this.name = name;
this.discussionId = discussionId;
}
I create some instance of this class and I store them in a listview.
When I double click on a listViewItem (it only show the name property), I navigate to another page that need to know the discussionId.
How can I get this property ?
This is how I navigate to the new page :
public partial class DiscussionPage : Page
{
public DiscussionPage()
{
InitializeComponent();
try
{
SqlDataReader read = Broker.sqlcommand("SELECT DISCUSSION.TITRE, USER1.NOM FROM dbo.DISCUSSION, dbo.USER1 WHERE USER1.ID = DISCUSSION.ID_CREER;").ExecuteReader();
while (read.Read())
{
Discussion d = new Discussion(read["TITRE"].ToString(), read["NOM"].ToString());
listDiscussion.Items.Add(d);
}
}
catch (Exception)
{
throw;
}
}
private void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
DependencyObject clickedObj = (DependencyObject)e.OriginalSource;
while (clickedObj != null && clickedObj != listDiscussion)
{
if (clickedObj.GetType() == typeof(ListViewItem))
{
Discussion selectedDiscussion = (Discussion)listDiscussion.SelectedItem;
this.NavigationService.Navigate(new MessagePage(selectedDiscussion));
break;
}
clickedObj = VisualTreeHelper.GetParent(clickedObj);
}
}
private void openAddDiscussion(object sender, RoutedEventArgs e)
{
addDiscussion add = new addDiscussion();
add.Show();
}
}
I need to know discussionId to load the content of this page :
public partial class MessagePage : Page
{
public MessagePage(Discussion SelectedDiscussion)
{
InitializeComponent();
try
{
SqlDataReader read = Broker.sqlcommand("SELECT MESSAGE.TEXT FROM dbo.MESSAGE WHERE MESSAGE.ID_POSSEDER = \'" + SelectedDiscussion.discussionId + "\'").ExecuteReader();
while (read.Read())
{
Message m = new Message(read["TEXT"].ToString());
showMessage.Items.Add(m);
}
}
catch (Exception)
{
throw;
}
}
}
Full code added, still don't work with SelectedValue:
incoherent Accessibility: parameter type 'commApp.Classes.Discussion' is less accessible than method 'commApp.MessagePage.MessagePage (commApp.Classes.Discussion)'
Without a good, minimal, complete code example, it's impossible to know for sure what the best approach is.
However, if you have set your ListView up correctly and the ItemsSource is a collection of Discussion objects, then by default the SelectedValue property will return the Discussion object instance reference that corresponds to the selected item in the list.
In that case, you would just change your code to look like this:
private void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
DependencyObject clickedObj = (DependencyObject)e.OriginalSource;
while (clickedObj != null && clickedObj != listDiscussion)
{
if (clickedObj.GetType() == typeof(ListViewItem))
{
Discussion selectedDiscussion = (Discussion)listDiscussion.SelectedValue;
this.NavigationService.Navigate(new MessagePage(selectedDiscussion));
break;
}
clickedObj = VisualTreeHelper.GetParent(clickedObj);
}
}
I.e. just use the SelectedValue property instead of SelectedItem. If you have deviated from the default by setting the SelectedValuePath property, then you will want to use the ItemContainerGenerator object to get the correct reference:
private void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
DependencyObject clickedObj = (DependencyObject)e.OriginalSource;
while (clickedObj != null && clickedObj != listDiscussion)
{
if (clickedObj.GetType() == typeof(ListViewItem))
{
Discussion selectedDiscussion =
(Discussion)listDiscussion.ItemContainerGenerator
.ItemFromContainer((ListViewItem)listDiscussion.SelectedItem);
this.NavigationService.Navigate(new MessagePage(selectedDiscussion));
break;
}
clickedObj = VisualTreeHelper.GetParent(clickedObj);
}
}
If neither of those seem to apply in your case, please edit your question so that it includes a good code example, with which a better answer can be provided.