Programmatically change Dropdown Menu Options in Unity3D - c#

i got Unity3D 5.2 and use the Dropdown GUI element for the first time. It is easy to use in the insepctor but i want the Options to show, be dependent of my files in Resources/Shapes/
So the dropdown should show all filenames i got in Resources/Shapes/ but i can not get a hold of this property in the attached C# script.
After reading the manual on Dropdown, there should be a property with the name "Options" and it should have a string and an image variable. (So for my understanding its a two dimensional array-ish type)
Unfortunately i cant use the following script (pseudo code since it doesnt work)
GameObject obj = GameObject.Find("Dropdown");
var info = new DirectoryInfo("Assets/Resources/Shapes");
var fileInfo = info.GetFiles();
foreach (var file in fileInfo)
{
//Add OptionsString Pseudo-Code
obj.Options += file; // Options doesnt exist
}
Can anyone explain to me how i can manipulate the Options property on my Dropdown menu pls, i cant find anything in google. Only old ways from before the time Unity had a built in Dropdown menu
Thanks in advance

List<string> list = new List<string> { "option1", "option2" };
var dropdown = GetComponent<Dropdown>();
dropdown.options.Clear();
foreach (string option in list)
{
dropdown.options.Add(new Dropdown.OptionData(option));
}

Found the answer:
Dropdown.OptionData list = new Dropdown.OptionData("Name");
obj.GetComponent<Dropdown>().options.Add(list);

The answares are correct, but are missing one line of code:
dropdown.RefreshShownValue();
After you add the values and set the selected option, you should refresh whats shown.
The full code for a TextMesh Pro Dropdown would be like:
List<string> list = new List<string> { "option1", "option2" };
dropdown.options.Clear();
foreach (string option in list)
{
dropdown.options.Add(new TMP_Dropdown.OptionData(option));
}
dropdown.value = 0;
dropdown.RefreshShownValue();

Related

How to save and load selected Dropdown values in unity

I am trying to make a dropdown that allows you to select different ways to display time. I got it all working except I need to find a way to save and load the option the player selected.
private void Start() {
timeDropdown.options.Clear();
List < string > items = new() {
"",
DateTime.Now.ToString(),
DateTime.Now.ToLongDateString(),
DateTime.Now.ToLongTimeString()
};
foreach(var item in items) {
timeDropdown.options.Add(new TMP_Dropdown.OptionData() {
text = item
});
}
DropdownItemSelected(timeDropdown);
timeDropdown.onValueChanged.AddListener(delegate {
DropdownItemSelected(timeDropdown);
});
}
void DropdownItemSelected(TMP_Dropdown timeDropdown) {
int index = timeDropdown.value;
timeText.text = timeDropdown.options[index].text;
}
I think you would use an int to save it but I don't know how to do that. Thank you.
You could use unity's player prefs system below is a link to documentation on how it works.
Unity player prefs documentaion
Alternatively you could create your serialisation system here's a Brackey's video which shows how to make a basic class serialisations system
YouTube tutorial
For what your trying to do the fastest and quickest approach would be to just use player prefs for saving and loading the int value.

c#, wpf, Dynamically naming controls

How do i create a new Button/Canvas with a dynamic name?
Button {buttonname read from text file} = new Button;
I have googled this for a while now but i can't find the solution.
Thank you!
I'm not sure if I understood correctly, but that name in your example is not the button name, it's just the reference name used in code to access the button. The button name would be set like this:
buttonRefName.Name = "ButtonName1";
So you can set the name to whatever you want: dynamically generated names inside a loop, names read from a file, etc...
You can use the same reference name for multiple buttons, just be sure to add it to List or to WPF Window, Panel, etc... before creating the new one:
var buttonList = new List<Button>();
var buttonRef = new Button { Name = "YourButtonName" };
buttonList.Add(buttonRef);
buttonRef = new Button { Name = "YourButtonName2" };
buttonList.Add(buttonRef);
It not possible the way you want to do it. If you are reading from a text file better use a List or better a Dictionary... an example use is as follows:
var buttons = new Dictionary<string, Button>();
buttons["yourName"] = new Button();
// logic goes here

How to move items from a checkedListBox to another checkedListBox

I made a program which adds checkedListBox.Items from a text written in a TextBox . Regarding this, to make everything more esthetic , I made a rule so that if the number of Items added in CheckedListBox1 is bigger than a number I set, it will go to a second CheckedListBox and so on.
I can also save my Entries in a .txt file so I have easy access to my previous references. So naturally I also made a Load References which ,obviously, load the file I saved.
Anyhow, my dillemma is the following : When I press the Load References button it loads ALL the references (Lines) in the text into the first checkedListBox. I want it to respect the previous law. If I click Load References I want that if there are more than, lets say, 10 entries, all the other ones will go into the other checkedListBox ,by consequence, if the limit number is passed from the second checkedListBox the rest will go into the third one and so on.
I have searched StackOverflow and the Web for several solutions ,some of the more relevant ones :
First found link semi-regarding the subject
Second found link
So to not get it wrong I will state that I want to have all the entries that pass the limit be MOVED to another checkedlistBox ,not copied like the links would suggest.
This is the Line of code for my Load Reference button :
private void button8_Click(object sender, EventArgs e)
{
string fileData = File.ReadAllText(#" To-Do References .txt");
checkedListBox1.Items.AddRange(fileData.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries));
}
Also I tried several methods but this one seemed to be the closest ,even though I got almost no satisfactory result :
var i = checkedListBox1.Items.Count;
if (i >= 10)
checkedListBox2.Items.Insert(0, checkedListBox1.Items);
Regarding this line of code : It does get an entry send into the second checkedList Box it is just that the entry is called (Collection) and has nothing to do with my references.
I hope I made myself clear and thank you for support!
UPDATE
The marked answer works perfectly for this kind of program. As I have not found anything similar I believe this is most likely the best way to implement the separation of text lines into different checkedListBoxes.
if you populate listboxes properly there will be no need to move items
private void button8_Click(object sender, EventArgs e)
{
int limit = 10;
string[] fileData = File.ReadAllText(#" To-Do References .txt").Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
// this loop adds items to the 1st list until limit is reached
for(int i =0; i<limit && i<fileData.Length; i++)
checkedListBox1.Items.Add(fileData[i]);
// if there extra items, 2nd loop adds them to list №2
for(int i =limit; i<fileData.Length; i++)
checkedListBox2.Items.Add(fileData[i]);
}
Set a limit, and maybe a multiplier to control the checkedList the data will be added to.
int limit = 10;
int checkList = 1;
string[] fileData = File.ReadAllText(#" To-Do References .txt").Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < fileData.Length; i++)
{
if (i == limit * checkList)
{
checkList++;
}
switch (checkList)
{
case 1: checkedListBox1.Items.Add(fileData[i]); break;
case 2: checkedListBox2.Items.Add(fileData[i]); break;
case 3: checkedListBox3.Items.Add(fileData[i]); break;
}
}
As big as your text file gets, adding data to a checkedListBox just requires you to add a new line to the switch statement.
Well, my head is stuck in wpf land, so I would just bind it to a list of lists, in an itemscontrol, or something similar. Reading back, of course, it appears you are using winforms, so this may not be applicable...but i'll post anyways, because it can still be done this way using the WinForms DataRepeater control.
List<List<string>> mainList = new List<List<string>>();
int listIndex = 0;
string[] fileData = File.ReadAllText(#" To-Do References.txt").Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
for(int i = 0; i<=fileData.Length; i++)
{
mainList[listIndex].Add(fileData[i]);
if (i%10 == 0)
{
listIndex++;
}
}
Then bind the mainList to the control and configure your ItemTemplate.
There was lots of info on binding to the DataRepeater, but here's one link:
https://msdn.microsoft.com/en-us/library/cc488279.aspx

How to remove item from generic list that relates to item in listbox?

I have searched around but could not find any references.
How do I delete an item in a generic list that relates to items in a listbox?
I currently have a public static List<Employees> and a listbox named lstRecords, I can remove the item in the listbox just fine, but either everything is removed from the list or nothing at all.
This was my first set of code I was working with:
private void DeleteRecord()
{
if (lstRecords.Items.Count > 0)
{
for (int i = 0; i < lstRecords.Items.Count; i++)
{
if (lstRecords.GetSelected(i) == true)
{
Employees employeeRecord = lstRecords.SelectedItem as Employees;
employee.Remove(employeeRecord);
}
}
lstRecords.Items.Remove(lstRecords.SelectedItem);
}
}
}
This is my 2nd set of code I was working with, I have my List right under partial class, but this is all contained in a method.
private void DeleteRecord()
{
ListBox lstRecords = new ListBox();
List<object> employee = new List<object>();
employee.RemoveAt(lstRecords.SelectedIndex);
lstRecords.Items.RemoveAt(lstRecords.SelectedIndex);
}
So far I haven't gotten either set of code to work the way I would like it to, I'm obviously doing something wrong.
I have a few other blocks of code I played around with but these seemed to be headed in the right direction.
Eventually I'll need to be able to double click an item in the list to pull up the properties menu.
Your code runs fine you just have to make some small changes.
The first code block is Ok however I dont know where your lstRecords are.
But have a look at this just copy the code and run it after you have some records in your employee object.
It's createing a listbox in code then adds it to the form(Winforms) and having the lstRecords globaly.
ListBox lstRecords;
private void IntializeDemoListbox()
{
lstRecords = new ListBox();
this.Controls.Add(lstRecords);
foreach (var item in employee)
{
lstRecords.Items.Add(item);
}
}
And then you will be able to use your first set of code the other set will be like this.
private void DeleteRecord()
{
employee.RemoveAt(lstRecords.SelectedIndex);
lstRecords.Items.RemoveAt(lstRecords.SelectedIndex);
}
What you want to do is bind your ListBox to you List of employees. This post shows the binding and the comments shows the removing code as well. The idea is that when you remove an item from the DataSource, then you won't see it in the ListBox.
Binding Listbox to List<object>
The problem with the DeleteRecord() method is that the lstRecords object you just created isn't the ListBox that is on the form.

Loading search results in a new form

I have been working on trying to understand ArrayList but I have run into a problem with the final part of my search function.
I have an array list set up to take data in from a StreamReader. The data consists of numerous properties to do with teams, such as their name and the image path to their logo.
I have then created a search that scans through the array list for a specific piece of string input through a textbox by the user.
I have then created an if statement to open up a new form if that search was returned true.
I would like the new form to load up each property of the team according to the data searched for. E.g if I searched for "Liverpool" it would then come up with the manager name, stadium name as well as the searched for name in the new form. I do not know how to do this.
The only tool that I can really think of to do this is the load.event procedure but I can not find a lot of information about linking it to an array list.
private void btn_Search_Click(object sender, EventArgs e)
{
foreach (Object obj in allTeams)
{
Team = (Team)obj;
if (team.teamName.ToUpper() == nameToMatch.ToUpper()) //case insensitive search.
{
FormTeam frmTeam = new FormTeam(Team); //windows form that displays team info.
frmTeam.Visible = true;
break;
}
}
}
above is my search function. (I have not used List<T> because it was required that everything must be stored in an ArrayList.)
Is what I am trying to achieve possible? And if so how?
Also, you may want to use Linq on your ArrayList
foreach(var team in allTeams.OfType<Team>())
{
if(team.TeamName.Equals(nameToMatch, StringComparison.InvariantCultureIgnoreCase))
{
frmTeam = new FormTeam(Team);
Aplication.Run(frmTeam); // or frmTeam.Show();
break;
}
}
Inside the Constructor of your TeamForm class you simply assign all Values from the Team- Object to the fields on the Form.
public FormTeam (Team team)
{
teamName.Text = team.TeamName; // label or something
teamPlayerCount.text = team.PlayerCount.ToString();
...
}
If you need to search on a string such as the teamName, it would be better to use something like a Dictionary<string,Team> rather than an Arraylist. Then you'd be able to do
Team t = dic[nameToMatch.ToUpper()];
where dic is the instance of Dictionary<string,Team> that contains all your teams.
First, you're missing a variable name there. I think you meant
foreach (Object obj in allTeams)
{
Team t = (Team)obj;
if (t.teamName.ToUpper() == nameToMatch.ToUpper()) //case insensitive search.
{
FormTeam frmTeam = new FormTeam(t); //windows form that displays team info.
frmTeam.Visible = true;
break;
}
}
But why not used a typed generic List, not have to do all this silly casting.
But your question is "how can I pass what I searched to the new form", correct? I'd change the constructor for FormTeam to something like FormTeam(Team t, string nameToMatch) and save the value locally in TeamForm so you can do highlighting or whatever.

Categories

Resources