WPF - Combobox - Add Item when user enter text in combo - wpf

I have a ComboBox binded with an ObservableCollection. How can I do when user enter a text in the ComboBox, if item not in the list, the code automatically add a new item to the list?
<ComboBox Name="cbTypePLC"
Height="22"
ItemsSource="{StaticResource TypePLCList}"
SelectedItem="{Binding TypePLC}" IsReadOnly="False" IsEditable="True">
</ComboBox>

Bind Text property of your combo box to your view model item and then add to the bound collection there, like,
Text="{Binding UserEnteredItem, UpdateSourceTrigger=LostFocus}"
Change the UpdateSourceTrigger to LostFocus because default (PropertyChanged) will communicate each character change to your viewmodel.
// user entered value
private string mUserEnteredItem;
public string UserEnteredItem {
get {
return mUserEnteredItem;
}
set {
if (mUserEnteredItem != value) {
mUserEnteredItem = value;
TypePLCList.Add (mUserEnteredItem);
// maybe you want to set the selected item to user entered value
TypePLC = mUserEnteredItem;
}
}
}
// your selected item
private string mTypePLC;
public string TypePLC {
get {
return mTypePLC;
}
set {
if (mTypePLC != value) {
mTypePLC = value;
// notify change of TypePLC INPC
}
}
}
// your itemsource
public ObservableCollection <string> TypePLCList { set; private set;}

Related

Binding WPF combobox with changed collection

I have a combobox inside a list where the items of the combo box are dynamic. They will be determined by the help of the selected item.
For example: If selected item is Item1 then combobox should contain Item1, Item2, Item3 but if selected item is Item2 then combo box should contain Item2, Item3, Item4
How to achieve the same by using binding..
Right now i am setting up two properties in my collection called SelectedValue and ListValues and binding them with my combobox but it only select first item of the list and leaving the rest one as it is.
Also, what is the order of execution of data binding as i want first Itemsource to call then selectedvalue should be set so that items will be selected.
Really appreciate for any help.
Here is my effort which works out but i am not sure if it's correct or not.
C#
public string SelectedValue
{
get
{
PropertyChanged.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs("Values"));
return _value;
}
set
{
if (value != null) //It will be null when binding of values happens
{
_value = value;
PropertyChanged.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs("Values"));
PropertyChanged.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs("SelectedValue"));
}
}
}
public IList<SomeType> Values
{
get
{
string status =_status;
return SomeFunctionToReturnValues(status);
}
}
XAML
<ComboBox SelectedValue="{Binding SelectedValue}" SelectedValuePath="Id" DisplayMemberPath="Text" Width="120" ItemsSource="{Binding Values,Mode=OneWay}"></ComboBox>
Please comment and Let me know if anyone can provide me better suggestion here.
You shold use ItemsSource property
<ComboBox SelectedItem="{Binding MyNum}" ItemsSource="{Binding Numbers}" Width="100" Height="30"/>
That bound to:
// Fills up combo box
public IEnumerable<int> Numbers
{
get
{
IEnumerable<int> temp = MyCollection.ToList();
return temp.SubArray(MyNum,MyCollection.count);
}
}
private int _myNum
public int MyNum
{
get
{
return _myNum;
}
set
{
_myNum = value;
OnPropertyChanged("MyNum");
}
}
When the SubArray is (Credit)
public static T[] SubArray<T>(this T[] data, int index, int length)
{
T[] result = new T[length];
Array.Copy(data, index, result, 0, length);
return result;
}

Display text on combo box

Im using combo box and I have a list that opened when you choose the arrow,I want
to put text on the combo box that you will see it witout opening the combo box,
how can I do that?
currently I try with text="name" ,name="name" witout success ,the combo box doesnt
display anything as a text. just list from drop down...
like the following
http://msdn.microsoft.com/en-us/library/ms753382%28v=vs.85%29.aspx
in addition how can I change the arrow like to be like in the link
Set the first item in the collection list as the default selection.
There is an example here:
How to show text in combobox when no item selected?
EDIT :
public class MyViewModel
{
public MyViewModel()
{
Items.Add("Select one item");
Items.Add("Item1");
Items.Add("Item2");
Items.Add("Item3");
SelectedItem = Items[0];
}
private List<String> _items;
public List<String> Items
{
get{ return _items; }
set
{
_items = value;
RaisePropertyChanged(() => Items);
}
}
private String> _selectedItem;
public String SelectedItem
{
get{ return _selectedItem; }
set
{
_selectedItem= value;
RaisePropertyChanged(() => SelectedItem);
}
}
}
In your xaml file you have to bind to the list of items and to the selected item:
<ComboBox x:Name="myComboBox"
ItemsSource="{Binding Items}"
SelectedValue="{Binding SelectedItem}" />
And don't forget to set the DataContext to your view model.

How to bind property to a TreeView

I want to create a relationship between my treeview and datagrid
I have a method called SelectedTestElement that calls a the SearchGrid method
ViewModel:
public TestElementViewModel SelectedTestElement
{
set
{
if (_selectedTestElement == value) return;
this._ selectedTestElement = value;
SearchGrid(value.Id, new List< TestElementViewModel>( testElementViewModel.GetAllTreeNodes()));
}
get
{
return this._ selectedTestElement;
}
}
I want to bind this property in my xaml TreeView
<TreeView Margin="644,137,6,6" Grid.RowSpan="2" ItemsSource="{Binding MessageElements, Mode=TwoWay}" TreeViewItem.Selected="{Binding SelectedTestElement, Mode=TwoWay}" />
Is treeView.Selected a best way to make the property call in treeview?
Edit:
ViewModel:
I select a treenode i.e SelectedTreeNode will be bind to TreeView.SelectedItem
public TreeNodeViewModel SelectedTreeNode
{
set
{
if (_selectedTreeNode== value) return;
this._selectedTreeNode = value;
//search the treenode id
SearchGrid(value.Id, TestFieldVModel.GetAllTestField());
}
get
{
return this._selectedTreeNode;
}
}
//do the search and highlight the matching id grid
public void SearchGrid(int id, ObservableCollection<TestFieldViewModel> msgField)
{
foreach (var c in msgField)
{
c.DisplayColor = c.Id == id ? Brushes.DarkOrange : Brushes.Black;
c.DisplayFont = c.Id == id ? FontWeights.Bold : FontWeights.Normal;
// SearchGrid(id, c.GetAllTestField());
}
}
XAML:
<TreeView Margin="644,137,6,6" Grid.RowSpan="2" ItemsSource="{Binding TreeNodes, Mode=TwoWay}" TreeView.SelectedItem ="{Binding Path= SelectedTreeNode, Mode=TwoWay}" >
This won't work, you're trying to bind an event to a property on your view model.
I would recommend that you use the TreeView.SelectedItem property and bind that to a new property on your view model that accepts a TreeViewItem. Then either modify your SelectedTestElement property to look at the new selected item property and determine the appropriate TestElementViewModel to return, or you could have the set of the new selected item property set the `this._selectedTestElement' directly.

Cascading two comboboxes - Child Combobox not selecting current value

Issue Summary
When using 2 cascading comboboxes, the child combobox does not select the current item, instead an empty item (I don't know where it comes from!) gets selected.
Issue Details
I have two comboboxes declared in xaml as given below. The two entities in play are StandardRack and RelayConfig
XAML:
<ComboBox ItemsSource="{Binding StandardRacks}" DisplayMemberPath="Name"
SelectedItem="{Binding StandardRack, Mode=TwoWay}" SelectedValuePath="Id"
<ComboBox ItemsSource="{Binding RelayConfigs}" DisplayMemberPath="DisplayName"
SelectedValue="{Binding DefaultRelayConfig, Mode=TwoWay}" SelectedValuePath="Id"
Here are the backing properties, and code to load comboboxes in ViewModel
ViewModel
private ObservableCollection<StandardRack> _standardRacks;
public ObservableCollection<StandardRack> StandardRacks {
get { return _standardRacks; }
set { _standardRacks = value; RaisePropertyChanged(() => StandardRacks); }
}
private StandardRack _standardRack;
public StandardRack StandardRack {
get { return _standardRack; }
set {
if (_standardRack != value) {
_standardRack = value;
LoadRelayConfigs();
RaisePropertyChanged(() => StandardRack);
}
}
}
private ObservableCollection<RelayConfig> _relayConfigs;
public ObservableCollection<RelayConfig> RelayConfigs {
get { return _relayConfigs; }
set { _relayConfigs = value; RaisePropertyChanged(() => RelayConfigs); }
}
private RelayConfig _defaultRelayConfig;
public RelayConfig DefaultRelayConfig {
get { return _defaultRelayConfig; }
set { _defaultRelayConfig = value; RaisePropertyChanged(() => DefaultRelayConfig); }
}
private void LoadRack() {
StandardRacks = new ObservableCollection<StandardRack>(
unitOfWork.StandardRackRepository.GetQueryable().Include(sr => sr.StandardRelay).ToList());
if (StandardRacks.Count > 0) {
StandardRack = Rack.StandardRack; //Set the current value of StandardRacks combobox
}
}
//Loads RelayConfigs Combobox based on Current Value of StandardRacks Combobox
private void LoadRelayConfigs() {
RelayConfigs = new ObservableCollection<RelayConfig>(
unitOfWork.RelayConfigRepository.GetQueryable()
.Where(rc => rc.StandardRelays.Any(srl => srl.Id == StandardRack.StandardRelay.Id)).ToList());
DefaultRelayConfig = Rack.DefaultRelayConfig; //Set Current Value of RelayConfigs Combobox. Does not work.
}
The above code loads both the comboboxes (StandardRacks and RelayConfigs) items properly. However the RelayConfigs selected value is not set to the one it is pointing to from XAML. Instead I get an empty item in the RelayConfigs Combobox as the current item.
Is the 'DefaultRelayConfig' part of the 'RelayConfigs' selection?

How to set ItemSource and ItemTemplate to display a list of objects

I have a List box that I want to display a list of objects, I am following the MVVM pattern and am finding it difficult to achieve what I want.
MainWindowView.xaml
<ListBox ItemsSource="{Binding Path=MyList}">
<ListBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Path=Name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
MainWindowViewModel.cs
private List<ListBoxItem> _myList = new List<ListBoxItem>();
public List<ListBoxItem> MyList
{
get { return _myList ; }
set
{
_myList = value;
OnPropertyChanged("MyList");
}
}
public SprintBacklogViewModel()
{
foreach(MyObject obj in MyObjects.MyObjectList)
{
ListBoxItem item = new ListBoxItem();
item.Content = obj;
MyList.Add(item);
}
}
MyList is getting updated correctly, but nothing is displaying in the window. (ItemsSource="{Binding Path=MyList}" also works, I tested with different data) I have not used an ItemTemplate before so any pointers are welcome. My understanding of it is that If I set it up correctly It will display the data in my objects.
eg:
<Label Content="{Binding Path=Name}"/>
there is a property in MyObject called Name, I want to display this as a label in my list
*EDIT
In my window I get a line of text - mynamespace.MyObject
MyList property in ViewModel is property of type ListBoxItem, it has property Name but it's not Name of MyObject. So you need to change your property in your ViewModel by
Replace
private List<ListBoxItem> _myList = new List<ListBoxItem>();
public List<ListBoxItem> MyList
{
get { return _myList ; }
set
{
_myList = value;
OnPropertyChanged("MyList");
}
}
with
private List<MyObject> _myList = new List<MyObject>();
public List<MyObject> MyList
{
get { return _myList ; }
set
{
_myList = value;
OnPropertyChanged("MyList");
}
}
Your list should not contain UI-Elements but data (you are data-binding), if you bind to a list of ListBoxItems the ListBox will disregard the ItemTemplate and just use the items as they fit the expected container for the ListBox. Containers will be generated automatically, you do not need to do that in your list.
If you add items to a collection at runtime the binding engine needs to be notified to update the changes, for this you should use an ObservableCollection or anything that implements INotifyCollectionChanged. (When doing so you further usually make the field readonly and only provide a getter) This is the reason why there are no items.

Resources