I am new to WPF and am having issues with associating a value with an object. I have a TreeView with CheckBoxes and I am wondering how I can associate an object to each checkbox. I want to be able to select all the checked checkboxes (no problem) and get a list of objects that are associated with each checked box.
For example, let's say I have a class called Fruit that has properties DisplayName and Price
TreeView:
Mango
✓ Apple
Orange
I want to be able to return the Apple object so that I can get the Price and other properties associated to the Fruit.
Here is a code sample for me adding checkboxes to the TreeView
TreeViewItem treeViewItem = new TreeViewItem();
CheckBox chkBox = new CheckBox();
chkBox.IsChecked = false;
chkBox.Content = "Value";
chkBox.IsThreeState = false;
chkBox.Click += chkBox_Click;
treeViewItem.Header = chkBox;
TreeViewItem inherits from FrameworkElement which provides the Tag property for this very purpose. You can set this property to an arbitrary object of your choosing. In this case, you would set it to the appropriate fruit object.
Example:
chkBox.Tag = appleObj;
Another Option
As an option, have you considered binding the TreeView's ItemsSource property to a collection of your fruit objects? You would set the TreeView's DisplayMemember property (which in inherits from ItemsControl) to the property on your fruit class that contains the name of the particular fruit. This would save you the work of hard-coding your check boxes.
Related
Hello I have set of check boxes that are generated from source code and not in XAML. Now, I wanted to set x:Name during creation of it so that I can loop through each element using the FindByName. I planned on setting name like checkbox1, checkbox2, checkbox3...
So that I can use this FindByName
foreach (var qaItem in question.Entity.QuestionAnswer)
{
(FindByName($"checkbox{qaItem.OrderNum}") as CheckBox).IsChecked = false;
}
Is there a way to set "x:Name" in source? since the number of checkboxes is not definite.
x:Name is not actually a property, it is just a XAML helper that is used to create a C# variable name. If you are creating the elements at runtime, you need to maintain an array or list in order to keep track of them
you could do something like this
Dictionary<string,Checkbox> myCheckboxList = new Dictionary<string,Checkbox>();
then as you create each checbox
var cb = new Checkbox();
... set properties, etc ...
myCheckboxList.Add(qaItem.OrderNum, cb);
been searching for a solution for this problem, found plenty solutions, but nothing changed my code's behaviour. This is in WinForms.
I am loading a form with a ComboBox, that contains the values and names of this enum, that is inside a class named "Node".
class Node
{
public enum NodeType { Yield, Home, Parking, Light, None, Inbound, Outbound }
public NodeType Type;
}
Then in my form, I have a ComboBox named "Type", which is set up like so (from the constructor):
Node node = new Node();
node.Type = Node.NodeType.Home;
Type = new ComboBox();
Type.Location = new Point(77, 41);
Type.Size = new Size(121, 24);
Type.DropDownStyle = ComboBoxStyle.DropDownList;
Type.DisplayMember = "Name";
Type.ValueMember = "Value";
Type.DataSource = Enum.GetValues(typeof(Node.NodeType));
Type.SelectedValue = node.Type;
Controls.Add(Type);
When the program runs, the list shows all the names, and on closing the form I am able to retrieve the selected value via. Type.SelectedValue. My problem is that the ComboBox doesn't start at the value that the Node is already set at. Essentially the line
Type.SelectedValue = node.Type;
doesn't do anything. I've tried using SelectedItem which didn't change anything, and
Type.SelectedIndex = (int)node.Type;
Which caused an ArgumentOutOfRangeException.
So, my question is: how do I set the start value of the ComboBox?
There are several mistakes in that code.
First, enum does not have Name and Value properties (in fact it does not have any property), so DisplayMember and ValueMember cannot be used and should be left blank (default). Which in turn means SelectedValue cannot be used and you need to use SelectedItem instead.
Second, you are using list data bound mode for the list portion of your ComboBox by setting DataSource property instead of populating Items, which is fine, but data binding occurs later in the process, so inside the constructor the Items property is empty and SelectedItem has no effect. In order to fix that, you need to move the data initialization part to your form Load event.
So, in your form constructor you'll have this:
Type = new ComboBox();
Type.Location = new Point(77, 41);
Type.Size = new Size(121, 24);
Type.DropDownStyle = ComboBoxStyle.DropDownList;
Controls.Add(Type);
and in your form Load event - this:
Node node = new Node();
node.Type = Node.NodeType.Home;
Type.DataSource = Enum.GetValues(typeof(Node.NodeType));
Type.SelectedItem = node.Type;
Type.SelectedIndex = index from your enum, for example the enum is {"apple", "pear", "pineapple"}, and you want pear by deafult, so Type.SelectedIndex = 1
This is my code to populate a ListBox named delBooks with a ListViewItem object and items .Text and .Tag properties.
ListViewItem item = new ListViewItem();
item.Text = "ss"; // Or whatever display text you need
item.Tag = "dd";
delBooks.Items.Add(item);
The output I see in the ListBox looks like this:
ListViewItem: {ss}
How can I correct this so it will display ss in the ListBox?
Set the DisplayMember on the ListBox to Text (as a string).
An object like ListViewItem does not exist for ListBox. This is one of the reasons that the ListBox control was superseded by the ListView control. In order to get ListViewItem like functionality out of a ListBox control you must implement your own object
class ListBoxItem
{
public string Text { get; set; }
public string Tag { get; set; }
public ListBoxItem(string text, string tag)
{
this.Text = text;
this.Tag = tag;
}
}
To populate the ListBox with your custom object simply do:
listbox.DisplayMember = "Text";
listbox.Items.Add(new ListBoxItem("ss", "dd"));
Where the .DisplayMember property of ListBox is the name of the property of your custom object that is to be displayed in the ListBox to the user.
If you need to access your custom objects values based on your ListBox item collection you can do a simple cast to retrieve the these values:
MessageBox.Show( ((ListBoxItem)listbox.Items[0]).Tag) );
Where the .Tag property is the value "dd" that we set earlier
PS: If you're a stickler for design like I am this method will also work with a struct
EDIT: If you are truly dead set on using ListViewItem you technically can just by setting the .DisplayMember to (in your case) the .Text property of the ListViewItem object
you need to change your last line like "delBooks.Items.Add(item.Text.toString());"
I'm having an issue when I select an item from a DataGridComboBoxColumn. The cell wont display the name of the item I've chosen after I move focus to the next cell. This is the code I have:
DataGridComboBoxColumn cb1 = new DataGridComboBoxColumn();
cb1.ItemsSource = listOStrings;
cb1.TextBinding = new Binding("listOfStrings");
e.Column = cb1;
e.Column.Header = "SomeTitle";
Where listOfStrings is a list that is being updated by the user. I have another DataGridComboBoxColumn that has its ItemSource set to a list of strings that isn't being updated. That one displays the text just fine, although the code for the two is the same. I'm wondering why my cb1 combo box wont display the values after leaving the cell but the other one does?
When a binding in WPF is hooked up to a non-static source, the underlying source needs to implement iNotifyPropertyChanged. In your case you may want to use an ObservableCollection as answered here: Why does a string INotifyPropertyChanged property update but not a List<string>?
In your case, it would look something like:
private ObservableCollection<string> _listOStrings = new ObservableCollection<string>();
public ObservableCollection<string> ListOStrings
{
get
{
return _listOStrings;
}
set
{
_listOStrings = value;
OnPropertyChanged("ListOStrings");
}
}
For more information on iNotifyPropertyChanged from MSDN, see:
See: https://msdn.microsoft.com/en-us/library/ms743695(v=vs.110).aspx
I've never done binding the way you are doing it - have you considered moving the UI to the XAML and databinding to a ViewModel? Here is an awesome step by step example on databinding comboboxes. You would just have the combobox be a column within the DataGrid also - similar to this.
My combobox contains 'Control', 'Alt' & 'Shift'.
My predefined string in the settings class is 'Control'.
How do i compare those 2 Strings :
= SelectedItem in the Combobox
= predefined string in the settings class
Because i want to save the changed selectedItem in my settings class, so whenever i start the application again it should load the new SelectedItem in the Combobox.
Edit: Code looking actually like this, but it wont work.
if (cmbModifier.SelectedItem.ToString() != ClipboardPro.Properties.Settings.Default.SavedModifier.ToString())
{
modkey = cmbModifier.SelectedItem.ToString();
ClipboardPro.Properties.Settings.Default.SavedModifier = modkey;
ClipboardPro.Properties.Settings.Default.Save();
}
the SelectedItem property returns the full listitem object you used to fill your combobox.
If you are looking for the value, you can use SelectedValue.ToString()
if (cmbModifier.SelectedValue.ToString() != ClipboardPro.Properties.Settings.Default.SavedModifier.ToString())
{
modkey = cmbModifier.SelectedValue.ToString();
ClipboardPro.Properties.Settings.Default.SavedModifier = modkey;
ClipboardPro.Properties.Settings.Default.Save();
}