Combine Text cell & ComboBox cell to a TreeView column GTK C#? - c#

I need to create a treeview column which contains both a text cell & Combobox cell.
I want to use a text cell if the value is one.
I want to use a Combobox cell if values are more than one.
Can you please share help link or sample on this.
Thanks!
Vijay

Created CellRenderComboBox object and Add this object to TreeviewColumn object.
The User need to register cellRendererCombo.EditingStarted += CellEditingStartedHandler event for updating combo box runtime.
using System;
using System.Threading;
using Gtk;
public partial class MainWindow : Gtk.Window
{
private Gtk.TreeView treeview1;
private int guiThreadId;
private bool stop = false;
private int threadId = 0;
public delegate void ThreadStart();
public MainWindow() : base(Gtk.WindowType.Toplevel)
{
Build();
guiThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
// Create our TreeView
treeview1 = new Gtk.TreeView();
Gtk.ScrolledWindow scrolledWindow = new ScrolledWindow();
scrolledWindow.Add(treeview1);
Gtk.VBox vBox = new VBox();
vBox.Add(scrolledWindow);
this.Add(vBox);
CellRendererCombo cellRendererCombo = new CellRendererCombo();
Gtk.TreeViewColumn treeViewColumn = new TreeViewColumn();
treeViewColumn.Title = "TYPE";
treeViewColumn.PackStart(cellRendererCombo, false);
treeViewColumn.AddAttribute(cellRendererCombo, "text", 0);
cellRendererCombo.Editable = true;
cellRendererCombo.Model = new Gtk.ListStore(typeof(string));
cellRendererCombo.Mode = CellRendererMode.Editable;
cellRendererCombo.TextColumn = 0;
cellRendererCombo.HasEntry = false;
cellRendererCombo.WidthChars = 20;
cellRendererCombo.Style = Pango.Style.Normal;
cellRendererCombo.Edited += OnActionChanged;
cellRendererCombo.EditingStarted += CellEditingStartedHandler;
treeview1.AppendColumn(treeViewColumn);
Gtk.ListStore listStore = new ListStore(typeof(string));
listStore.AppendValues("A");
listStore.AppendValues("B");
}
protected void OnEdited(object sender, Gtk.EditedArgs args)
{
Gtk.TreeSelection selection = treeview1.Selection;
Gtk.TreeIter iter;
selection.GetSelected(out iter);
treeview1.Model.SetValue(iter, 1, args.NewText); // the CellRendererText
}
protected void CellEditingStartedHandler(object o, EditingStartedArgs args)
{
Console.WriteLine($"CellEditingStartedHandler");
if (o is Gtk.CellRendererCombo)
{
Gtk.CellRendererCombo cellRendererCombo = (Gtk.CellRendererCombo)o;
((Gtk.ListStore)cellRendererCombo.Model).Clear();
((Gtk.ListStore)cellRendererCombo.Model).AppendValues("A");
((Gtk.ListStore)cellRendererCombo.Model).AppendValues("B");
}
}
}

Related

String to existing object

So i have my buttons like this :
text : Skarl, Name : btnHeroe1
text : Kled, Name : btnHeroe2
text : Kled, Name : btnHeroe3
My object are like this (price, damage)
Heroe Heroe1 = new Heroe(100,5);
Heroe Heroe2 = new Heroe(500,10);
Heroe Heroe3 = new Heroe(100,40);
They have properties (price,dps,level)
And when i click on my button, i use this method with these lines to get the name of the button pressed :
Button b = sender as Button;
string vButton = b.Name;
string strHeroeToBuy = vButton.Substring(3, vButton.Length - 3);
Now i'm asking. How can i get the properties like this : strHeroeToBuy.Price ?
Edit : Solved it by getting the id of my heroes and searching with button have the same id
If you keep your heroes in a list, and give them unique ids then you can find them:
// The id can be an int or a string, it's your choice
Heroes = new List<Heroe> {
new Heroe(id: 1, 100,5),
new Heroe(id: 2, 500,10),
new Heroe(id: 3, 100,40)
};
(...)
var id = //get Id from button
// needs 'using System.Linq'
var myHero = Heroes.FirstOrDefault( h => h.Id == id);
if(myHero == null) // error
One way to allow looking up an attribute would be to use a Dictionary, though it will require a unique key.
So, you would need to map your objects into the dictionary. Here is a sample console app to demonstrate:
using System;
using System.Collections.Generic;
namespace ConsoleApp
{
public class Hero
{
public Hero(int price, int points)
{
Price = price;
Points = points;
}
public int Price { get; set; }
public int Points { get; set; }
}
class Program
{
static void Main(string[] args)
{
var heros = new Dictionary<string, Hero>();
heros.Add("Hero1 Name", new Hero(10, 100));
heros.Add("Hero2 Name", new Hero(11, 101));
heros.Add("Hero3 Name", new Hero(12, 102));
if (heros.ContainsKey("Hero1 Name"))
{
Console.WriteLine(heros["Hero1 Name"].Price);
}
}
}
}
You could just store each hero in the .Tag() property of each button. Associate them in the Load() event of the form (assuming WinForms):
private Heroe Heroe1 = new Heroe(100,5);
private Heroe Heroe2 = new Heroe(500,10);
private Heroe Heroe3 = new Heroe(100,40);
private void Form1_Load(object sender, EventArgs e)
{
btnHeroe1.Tag = Heroe1;
btnHeroe2.Tag = Heroe2;
btnHeroe3.Tag = Heroe3;
}
Now you can just grab that hero from the tag:
Button b = sender as Button;
Heroe H = (Heroe)b.Tag;
// ... do something with "H" ...
You cannot do that for with a String. You could use the Tag-property on your Button to achieve it!
First you need a List of Heroes of some sort. This list need to be accessible from the form constructor, and from the click event.
public partial class Form1: Form
{
Hero[] data = new []{
new Hero{ Name= "Foo"},
new Hero{ Name= "Bar", Price=100, Dps=20, PropertyName=Value},
};
public Form1(){
// ...
}
// ...
}
At initialisation you will create the button based on your listing of heroes.
public Form1()
{
InitializeComponent();
// Have a Container that will hold the buttons
foreach(var hero in data){
var button = new Button();
//set text // set size
// set position. Compute it based on button size you just set.
// We put the whole hero in the tag not just the name `button.Tag = hero.Name`
button.Tag = hero;
// Add one even for all the button.
button.Click += new EventHandler(HeroButton_Click);
//Add button to the container
this.Controls.Add(button); // This or a container.
}
}
And the event that will be handle all the button click:
private void HeroButton_Click(object sender, EventArgs e)
{
Button btn = (Button) sender;
var hero = (Hero)btn.Tag
// Do thing with the Hero.
//Old Way, we search for the Hero in the list Data
// var hero = data.FirstOrDefault(x=> x.Name == (string)btn.Tag);
// if(hero==null) ; // error, could not find the hero
}

Check all items in a specified checked list box c#

I have created a small kitchen display program that display food orders. So I created dynamically a panel that contains a table layout panel that contains a checked list box and a check all button . My problem is... I have a check all button in each table layout panel created dynamically and every time I click it, it checks all items in the last created CheckedListBox not the clicked one.
This is my code:
p = new Panel();
p.Size = new System.Drawing.Size(360, 500);
p.BorderStyle = BorderStyle.FixedSingle;
p.Name = "panel";
tpanel = new TableLayoutPanel();
tpanel.Name = "tablepanel";
clb = new CheckedListBox();
tpanel.Controls.Add(b1 = new Button() { Text = "CheckAll" }, 1, 4);
b1.Name = "b1";
b1.Click += new EventHandler(CheckAll_Click);
b1.AutoSize = true;
private void CheckAll_Click(object sender, EventArgs e)
{
var buttonClicked = (Button)sender;
var c = GetAll(this, typeof(CheckedListBox));
for (int i = 0; i < c.Count(); i++)
{
\\any help
}
}
public IEnumerable<Control> GetAll(Control control, Type type)
{
var controls = control.Controls.Cast<Control>();
return controls.SelectMany(ctrl => GetAll(ctrl, type)).Concat(controls).Where(c =>
c.GetType() == type);
}
First I will describe the struct
Order = TableLayoutPanel
TableLayoutPanel has 1 CheckAll Button and CheckListBox
And you want when you click to CheckAll Button it will checks exactly all items in current TableLayoutPanel.
So try this code
class XForm : Form {
// create Dictionary to store Button and CheckListBox
IDictionary<Button, CheckListBox> map = new Dictionary<Button, CheckListBox> ();
// when you create new order (new TableLayoutPanel)
// just add map Button and CheckListBox to map
private void CreateOrder () {
var panel = new Panel ();
panel.Size = new System.Drawing.Size (360, 500);
panel.BorderStyle = BorderStyle.FixedSingle;
panel.Name = "panel";
var table = new TableLayoutPanel ();
var checklistBox = new CheckedListBox ();
var button = new Button () { Text = "CheckAll" };
table.Controls.Add (button, 1, 4);
button.Name = "b1";
button.Click += new EventHandler (CheckAll_Click);
button.AutoSize = true;
map[button] = checklistBox;
}
// and on event handle
private void CheckAll_Click (object sender, EventArgs e) {
var buttonClicked = (Button) sender;
var c = map[buttonClicked];
if (c == null) return;
for (int i = 0; i < c.Items.Count; i++)
{
c.SetItemChecked(i, true);
}
}
}
And dont for get remove it from map when remove the order.
Hope it helps

c# textbox shows object name instead of value

I have a form written in c#, with various drop down lists, but I'm having problems with a listbox on the form. I need to populate a textbox with the values selected from the listbox when I double click on them. I've got the click event working, but the textbox will only populate with the object name, not the value from the listbox
i.e.
'System.Windows.Controls.SelectedItemCollection'
instead of the actual value.
Here is the entire code block I'm working on:
I should have just done this at the start - here is the complete code block I'm working on:
else if (theValue.FieldName.Equals("UIPathList", StringComparison.OrdinalIgnoreCase) == true)
{
int nRow = 14;
Button theUIPathOptionsButton = new Button();
TextBox theOldValueTextBox = AddLabelAndOldValue(theHelper, nRow, theValue);
theOldValueTextBox.Text = theValue.OldValue.Replace(",", "," + Environment.NewLine);
theUIPathOuterStackPanel = new StackPanel
{
Visibility = Visibility.Visible,
Orientation = Orientation.Vertical,
Background = new SolidColorBrush(Colors.White),
ClipToBounds = true,
};
theUIPathOptionsInnerStackPanel = new StackPanel
{
Visibility = Visibility.Visible,
Orientation = Orientation.Horizontal,
Background = new SolidColorBrush(Colors.White)
};
theUIPathOuterStackPanel.ClipToBounds = true;
TextBox theNewTextBox = new TextBox
{
TabIndex = nRow,
TextWrapping = TextWrapping.Wrap,
AcceptsReturn = true,
};
theNewTextBox.Clear();
theNewTextBox.MouseDoubleClick += MultiLineChildDatapointList_HandleMouseDoubleClick;
theNewTextBox.Focusable = true;
theNewTextBox.HorizontalAlignment = HorizontalAlignment.Stretch;
theNewTextBox.Width = 365;
theNewTextBox.PreviewKeyDown += theGetMetadataHelper.Preview_KeyDown_IsMultilineText;
theNewTextBox.Tag = theValue;
ListBox theUIPathOptionslistBox = new ListBox();
theUIPathOptionslistBox.Items.Add("RuntimeDefaults");
theUIPathOptionslistBox.Items.Add("CommonSettings");
theUIPathOptionslistBox.Items.Add(InputDatapointManager.CONST_CHANGE_RECORD_CHANGES_CLEAR_VALUE);
theUIPathOptionslistBox.TabIndex = nRow;
theUIPathOptionslistBox.SelectionMode = SelectionMode.Multiple;
theUIPathOptionslistBox.ClipToBounds = true;
theUIPathOptionslistBox.Focusable = true;
theUIPathOptionslistBox.Visibility = Visibility.Hidden;
theUIPathOptionslistBox.Height = 34;
theUIPathOptionsInnerStackPanel.Children.Add(theNewTextBox);
theUIPathOptionsInnerStackPanel.Children.Add(theUIPathOptionsButton);
theUIPathOuterStackPanel.Children.Add(theUIPathOptionsInnerStackPanel);
theUIPathOuterStackPanel.Children.Add(theUIPathOptionslistBox);
void button1_click(object sender, EventArgs e)
{
theUIPathOptionslistBox.Visibility = Visibility.Visible;
}
void button1_doubleclick(object sender, EventArgs e)
{
theNewTextBox.Text = theUIPathOptionslistBox.SelectedItem.ToString();
}
theUIPathOptionsButton.Click += button1_click;
theUIPathOptionslistBox.MouseDoubleClick += button1_doubleclick;
Grid.SetColumn(theUIPathOuterStackPanel, 4);
Grid.SetRow(theUIPathOuterStackPanel, nRow);
theDataGrid.Children.Add(theUIPathOuterStackPanel);
theEditControlList.Add(theNewTextBox);
}
This was (possibly) already answered here : Getting value of selected item in list box as string
string myItem = listBox1.GetItemText(listBox1.SelectedItem);
Then you just have to add your item to the textbox :
textBox1.Text = myItem;
If you don't want to create a new string variable, then this one is working too :
textBox1.Text = listBox1.SelectedItem.ToString();
ListBox, Item is a collection of objects, not strings, so you must let it know how to convert it to string, otherwise it will use its defualt .ToString() function that obviously the object currently in your items not giving the desired result.
Imagine items are oftype following class:
class SomeClass
{
public int Id;
public string Name;
}
You may do one of these three:
1.set the DisplayMember of your ListBox to Name
2.add override method to your class so that it overrides its .ToString() and return its Name property:
class SomeClass
{
public int Id;
public string Name;
public override string ToString()
{
return Name;
}
}
3.Just cast it to its real type and get the property you want:
SomeClass selected = (SomeClass)ListBox.SelectedItem;
TextBox1.Text = selected.Name;
This is because the TextBox will use the ToString() method on what it is bound to, which by default will return the class name.
You solutions are to either override the ToString() method of the class to return the value you want or set the text property of the TextBox to the text value you want rather then the object.
The solution I finally got to was as follows:
void theUIPathOptionslistBox_SelectedIndexChanged(object sender,
SelectionChangedEventArgs e)
{
theNewTextBox.Clear();
foreach (object selectedItem in theUIPathOptionslistBox.SelectedItems)
{
theNewTextBox.AppendText(selectedItem.ToString() + Environment.NewLine);
}
}
theUIPathOptionslistBox.SelectionChanged +=
theUIPathOptionslistBox_SelectedIndexChanged;

Binding without XAML [WPF]

I am designing an application with 256 buttons inside, and I am adding them in the WrapPanel in C# code using for loop. These buttons are not mentioned in XAML code.
My problem is that, when clicking on one of them, I have to change its color using binding.
I tried following code, but it does not work (only changes the content of the button):
private void NewButton_Click(object sender, RoutedEventArgs e)
{
Button btn = (Button)sender;
for (int i = 0; i < counter; i++)
{
if (btn.Name == ("Butt" + i))
{
btn.Content = "works";
MyData mydata = new MyData();
Binding binding = new Binding("Color");
binding.Source = mydata;
binding.Source = btn;
break;
}
}
}
and
private int counter = 0;
public class MyData
{
public static Brush _Color = Brushes.Red;
public Brush Color
{
get
{
return _Color;
}
}
}
public MainWindow()
{
InitializeComponent();
int num = number(3);
List<Button> btnList = new List<Button>();
for(int i =0; i<(num*num); i++)
{
Button button = new Button();
button.Name = "Butt" + counter;
button.Content = "New";
counter++;
button.Height = 35;
button.Width = 35;
button.Click += new RoutedEventHandler(NewButton_Click);
wp.Children.Add(button);
}
If what you are trying to do is bind the button's background color to your "MyData" class object, you are almost there...
First, create the binding object, set the source to your new instance of "mydata", and then the path to your "Color" property exposed.
THEN, you need to save the new BINDING object to your button control and tell it you want the BackgroundProperty bound to the newly created binding. The following minor adjustment to your code works. Not exactly why your approach is what it is for your overall project, but hopefully does what you intended.
if (btn.Name == ("Butt" + i))
{
btn.Content = "works";
MyData mydata = new MyData();
var oBind = new Binding
{
// bind its source to this view model instance
Source = mydata,
// what property on THE BUTTON do want to be bound to.
Path = new PropertyPath("Color")
};
btn.SetBinding(BackgroundProperty, oBind);
btn.DataContext = oBind;
break;
}

Removing or Hide dynamically created linklabels and labels

Background
I create a set of linklabel and label controls using a loop that uses data from a database as there content (Text).
Question
How do I then remove or change there visibility?
What I would Like to Happen?
On a button click event, I would like all of the link's and linklabel's text properties to be set to either null, or their visibility properties to be set as false.
Code
private void getInfoStationID()
{
//SQL Connection Stuff
for (int i = 0; i <= rowCount - 1; i++)
{
LinkLabel Linklabel = new LinkLabel();
Linklabel.Text = ds.Tables[0].Rows[i] ["code"].ToString();
Linklabel.Height = 15;
Linklabel.Width = 50;
Linklabel.AutoSize = true;
Linklabel.Location = new Point(10, (i + 1) * 30);
tabControl1.TabPages[0].Controls.Add(Linklabel);
// Add an event handler to do something when the links are clicked.
Linklabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
Label label1 = new Label();
label1.Text = ds.Tables[0].Rows[i]["name"].ToString();
label1.Height = 15;
label1.Width = 70;
label1.Location = new Point(100, (i + 1) * 30);
tabControl1.TabPages[0].Controls.Add(label1);
Label label3 = new Label();
label3.Text = ds.Tables[0].Rows[i]["toc"].ToString();
label3.Height = 15;
label3.Width = 50;
label3.Location = new Point(240, (i + 1) * 30);
tabControl1.TabPages[0].Controls.Add(label3);
}
}
private void clearAllBtn_Click(object sender, EventArgs e)
{
//Would like this to clear all previously drawn labels and linklabels
}
Simply add the dynamic controls to a List so you have a quick reference to them:
// out at CLASS/FORM level:
private List<Control> MyControls = new List<Control>();
// ... some method ...
for (int i = 0; i <= rowCount - 1; i++)
{
LinkLabel Linklabel = new LinkLabel();
MyControls.Add(Linklabel);
// ... rest of your code ...
Label label1 = new Label();
MyControls.Add(label1);
// ... rest of your code ...
Label label3 = new Label();
MyControls.Add(label3);
// ... rest of your code ...
}
Now you can use that List from somewhere else:
private void clearAllBtn_Click(object sender, EventArgs e)
{
foreach(Control ctl in MyControls)
{
ctl.Visible = false; // or something else
}
}
*Don't forget to dispose of those controls and empty the list if you decide to create a new set of dynamic controls. If you want to completely get rid of them:
private void clearAllBtn_Click(object sender, EventArgs e)
{
foreach(Control ctl in MyControls)
{
ctl.Dispose();
}
MyControls.Clear();
}
You can loop through all controls on a certain tabpage. You could use a open generic function to make the code nice and clean. Like this:
private void HideControls<TControl>(Control parentControl)
where TControl : Control
{
var controls = parentControl.Controls.OfType<TControl>();
foreach (var control in controls)
{
control.Visible = false;
}
}
And use it like this:
private void button1_Click(object sender, EventArgs e)
{
this.HideControls<Label>(tabControl1.TabPages[0]);
this.HideControls<LinkLabel>(tabControl1.TabPages[0]);
}
You could even refactor this to a nice extension method:
public static class ControlExtensions
{
public static void HideControlsOfType<TControl>(this Control parentControl)
where TControl : Control
{
var controls = parentControl.Controls.OfType<TControl>();
foreach (var control in controls)
{
control.Visible = false;
}
}
}
and use like:
this.tabControl1.TabPages[0].HideControlsOfType<Label>();

Categories