I am going to create a ComboBox with availability of add item manually by user in WPF. So I have created some code like this:
My View code:
<ComboBox SelectedItem="{Binding Path=SelectedItem}" ItemsSource="{Binding ItemsSource}" Text="{Binding Path=InputText, UpdateSourceTrigger=LostFocus}" IsEditable="True"/>
My ViewModel code:
public class ViewModel : INotifyPropertyChanged
{
private string selectedIndex;
private string inputText;
public event PropertyChangedEventHandler PropertyChanged;
public string InputText
{
get { return inputText; }
set { inputText = value; OnPropertyChanged(); CheckAndInsertIfValid(); }
}
public string SelectedItem
{
get { return selectedIndex; }
set { selectedIndex = value; OnPropertyChanged(); }
}
public ObservableCollection<string> ItemsSource { get; set; }
public ViewModel()
{
ItemsSource = new ObservableCollection<string>()
{
"0", "1", "2", "3", "4" ,"5"
};
SelectedItem = ItemsSource[3];
}
public virtual void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private void CheckAndInsertIfValid()
{
if (InputText != "Some Values" && !ItemsSource.Contains(InputText))
ItemsSource.Add(InputText);
}
}
It works fine and user can add to ComboBox manually. But when view is showing to user SelectedItem will be "null" however I've set.
I don't know why SelectedItem is going to be null? And How can I prevent to change of SelectedItem?
The InputText property in your case doesn't seem necessary to me, you can get rid of it and bind directly to the SelectedItem property:
<ComboBox SelectedItem="{Binding Path=SelectedItem}" ItemsSource="{Binding ItemsSource,Mode=TwoWay}" Text="{Binding Path=SelectedItem, UpdateSourceTrigger=LostFocus}" IsEditable="True"/>
And change your VM accourdingly:
public class ViewModel : INotifyPropertyChanged
{
private string _selectedItem;
public event PropertyChangedEventHandler PropertyChanged;
public string SelectedItem
{
get { return _selectedItem; }
set { _selectedItem = value; OnPropertyChanged(); CheckAndInsertIfValid(); }
}
public ObservableCollection<string> ItemsSource { get; set; }
public ViewModel()
{
ItemsSource = new ObservableCollection<string>()
{
"0", "1", "2", "3", "4" ,"5"
};
SelectedItem = ItemsSource[3];
}
public virtual void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private void CheckAndInsertIfValid()
{
if (SelectedItem != "Some Values" && !ItemsSource.Contains(SelectedItem))
ItemsSource.Add(SelectedItem);
}
}
Related
My combo cbStudents is bound to StudentsList:
<ComboBox Name="cbStudents"
ItemsSource="{Binding Path=Students}"
SelectedItem="{Binding Path=SelectedStudent, Mode=TwoWay}"
DisplayMemberPath="Name"/>
public class Student
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
private int _age;
public int Age
{
get { return _age; }
set { _age= value; }
}
}
I want to get the SelectedItem:
I tried-
private ObservableCollection<Language> _students;
public ObservableCollection<Language> Students
{
get { return _students; }
set { _students= value; }
}
private string _selectedStudent;
public string SelectedStudent
{
get { return _selectedStudent; }
set { _selectedStudent= value; }
}
private void btnGetOutput(object sender, RoutedEventArgs e)
{
MessageBox.Show("Your selected item is: " + SelectedStudent);
}
Result:
I get Null output. No error code, nothing. Any help is appreciated.
It seems you want to select a student by its name, i.e. a string.
Instead of SelectedItem, you should then use SelectedValue and SelectValuePath:
<ComboBox
ItemsSource="{Binding Students}"
DisplayMemberPath="Name"
SelectedValuePath="Name"
SelectedValue="{Binding SelectedStudent}" />
The view model would of course have to implement INotifyPropertyChanged and should declare the Students property as a readonly:
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<Student> Students { get; }
= new ObservableCollection<Student>();
private string selectedStudent;
public string SelectedStudent
{
get { return selectedStudent; }
set
{
selectedStudent = value;
PropertyChanged?.Invoke(this,
new PropertyChangedEventArgs(nameof(SelectedStudent)));
}
}
}
First of all, you have defined ObservableCollection<Language> Students, I think it should be ObservableCollection<Student> Students instead.
Then, you have to bind to that collection, not to StudentList, which doesn't exist in your sample (maybe you didn't present full code?).
Then, you have to add items to that list somewhere, Students.Add(...).
Then, if items of your combo box are of type Student, then property bound to SelectedItem also must have type of Student, not string.
Last but not least: you have to bind class with all this fieelds defined to your view, so you must write: view.DataContext = objectWithData;, where view is your view and objectWithData is object with those fields defined.
You can implement INotifyPropertyChanged interface. As in the example below:
public class Data : INotifyPropertyChanged
{
// boiler-plate
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetValue<T>(ref T field, T value, string propertyName)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
private ObservableCollection<Language> _students;
public ObservableCollection<Language> Students
{
get { return _students; }
set { _students= value; }
}
private Language _selectedStudent;
public Language SelectedStudent
{
get { return _selectedStudent; }
set { SetValue(_selectedStudent, value, "SelectedStudent"); }
}
}
I'm trying to dynamically update an element's visibility by binding IsVisible to a getter property. However, the IsVisible does not automatically change the UI unless I refresh the page.
The following is the code snippet:
xaml:
<StackLayout>
<Picker Title="Choose..." ItemsSource="{Binding MyItemOptions}" SelectedItem="{Binding MyItem}"/>
<Label Text="MyItem is Milk" IsVisible="{Binding Path=IsMilkItem}"/>
</StackLayout>
C#:
private string _myItem;
public string MyItem
{
get => _myItem;
set
{
SetValue(ref _myItem, value);
}
}
public bool IsMilkItem
{
get { return MyItem == "Milk"; }
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetValue<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
bool response = false;
if (field == null ||
!field.Equals(value))
{
field = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
response = true;
}
return response;
}
The boolean property is updated in code after updating MyItem. However, the UI element does not automatically show up until i manually re-render the page.
I will be grateful if someone has a solution to this.
when you change the value of MyItem, it does not raise a PropertyChanged event for IsMilkItem, so the UI is never told to update
public string MyItem
{
get => _myItem;
set
{
SetValue(ref _myItem, value);
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsMilkItem"));
}
}
According to your description, you want to choose item from picker, when selecting item is Milk, you want to Label control is visible, Am I right?
If yes, I modify your code, you can take a look:
public partial class Page17 : ContentPage, INotifyPropertyChanged
{
public ObservableCollection<string> MyItemOptions { get; set; }
private string _MyItem;
public string MyItem
{
get { return _MyItem; }
set
{
_MyItem = value;
if(_MyItem== "Milk")
{
IsMilkItem = true;
}
else
{
IsMilkItem = false;
}
}
}
private bool _IsMilkItem;
public bool IsMilkItem
{
get { return _IsMilkItem; }
set
{
_IsMilkItem = value;
RaisePropertyChanged("IsMilkItem");
}
}
public Page17 ()
{
InitializeComponent ();
MyItemOptions = new ObservableCollection<string>()
{
"item 1",
"item 2",
"item 3",
"Milk"
};
this.BindingContext = this;
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Update:
You can use Label trigger to set label isvisible, and don't need to IsMilkItem property to set Lable Isvisible.
<Picker x:Name="picker1" Title="Choose..." ItemsSource="{Binding MyItemOptions}" SelectedItem="{Binding MyItem}" />
<Label Text="MyItem is Milk" IsVisible="False" >
<Label.Triggers>
<DataTrigger TargetType="Label" Binding="{Binding Source={x:Reference picker1},Path=SelectedItem}" Value="Milk">
<Setter Property="IsVisible"
Value="True"/>
</DataTrigger>
</Label.Triggers>
</Label>
Here is the .cs:
public ObservableCollection<string> MyItemOptions { get; set; }
private string _MyItem;
public string MyItem
{
get { return _MyItem; }
set
{
_MyItem = value;
}
}
public Page17 ()
{
InitializeComponent ();
MyItemOptions = new ObservableCollection<string>()
{
"item 1",
"item 2",
"item 3",
"Milk"
};
this.BindingContext = this;
}
I have ComboBox:
<ComboBox ItemsSource="{Binding Path=MonthDaysList}" IsSynchronizedWithCurrentItem="True"/>
Here is method to generate MonthDaysList data:
public ObservableCollection<string> MonthDaysList { get; internal set; }
public void GetMonths() {
MonthDaysList = new ObservableCollection<string>();
foreach (var item in MyConceptItems) {
MonthDaysList.Add(item.DateColumn);
}}
ObservableCollection & Binding are working fine, but it's not displayed default/first item into ComobBox:
It's possible to resolve it without set up Name of ComboBox?
Define a string source property in the view model and bind the SelectedItem property of the ComboBox to this one:
<ComboBox ItemsSource="{Binding Path=MonthDaysList}" SelectedItem="{Binding SelectedMonthDay}"/>
Make sure that you implement the INotifyPropertyChanged interface if you intend to set the source property dynamically:
public class ViewModel : INotifyPropertyChanged
{
private ObservableCollection<string> _monthDaysList;
public ObservableCollection<string> MonthDaysList
{
get { return _monthDaysList; }
internal set { _monthDaysList = value; OnPropertyChanged(); }
}
private string _selectedMonthDay;
public string SelectedMonthDay
{
get { return _selectedMonthDay; }
internal set { _selectedMonthDay = value; OnPropertyChanged(); }
}
public void GetMonths()
{
MonthDaysList = new ObservableCollection<string>();
if (MyConceptItems != null && MyConceptItems.Any())
{
foreach (var item in MyConceptItems)
{
MonthDaysList.Add(item.DateColumn);
}
SelectedMonthDay = MonthDaysList[0];
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
I want to populate my combobox2 after combobox1 selection changed event.
Here's some part of my XAML:
<ComboBox Name="cmbWorkcode"
ItemsSource="{Binding Workcodes}"
DisplayMemberPath="WorkcodeName"
SelectedValuePath="WorkcodeID"
SelectedValue="{Binding Path=WorkcodeId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<ComboBox Name="cmbProcess"
ItemsSource="{Binding Processes}"
DisplayMemberPath="ProcessName" SelectedValuePath="ProcessId"
SelectedValue="{Binding Path=ProcessId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
Some part of my ViewModel:
class MainWindowViewModel : ObservableObject
{
private ObservableCollection<Workcode> _workcodes = new ObservableCollection<Workcode>();
public ObservableCollection<Workcode> Workcodes
{
get { return _workcodes; }
set
{
_workcodes = value;
OnPropertyChanged("Workcodes");
}
}
private int _workcodeId;
public int WorkcodeId
{
get { return _workcodeId; }
set
{
_workcodeId = value;
OnPropertyChanged("WorkcodeId");
}
}
private ObservableCollection<Process> _processes = new ObservableCollection<Process>();
public ObservableCollection<Process> Processes
{
get { return _processes; }
set
{
_processes = value;
OnPropertyChanged("Processes");
}
}
private int _processId;
public int ProcessId
{
get { return _processId; }
set
{
_processId = value;
OnPropertyChanged("ProcessId");
}
}
public MainWindowViewModel()
{
PopulateWorkcode();
}
private void PopulateWorkcode()
{
using (var db = new DBAccess())
{
db.ConnectionString = ConfigurationManager.ConnectionStrings["connString"].ConnectionString;
db.Query = #"SELECT workcodeId, workcode FROM workcode";
DataTable data = db.GetData();
if (data != null)
{
foreach (DataRow row in data.Rows)
{
int workcodeId = Convert.ToInt32(row["workcodeId"].ToString());
string workcodeName = row["workcode"].ToString();
_workcodes.Add(new Workcode(workcodeId, workcodeName));
}
}
}
}
private void PopulateProcess()
{
using (var db = new DBAccess())
{
db.ConnectionString = ConfigurationManager.ConnectionStrings["connString"].ConnectionString;
db.Query = #"SELECT ProcessId, ProcessName FROM `process` WHERE WorkcodeId = #workcodeId";
DataTable data = db.GetData(new[] {new MySqlParameter("#workcodeId", _workcodeId.ToString())});
if (data != null)
{
foreach (DataRow row in data.Rows)
{
int id = Convert.ToInt32(row["ProcessId"].ToString());
string name = row["ProcessName"].ToString();
_processes.Add(new Process(id, name));
}
}
}
}
}
My problem is I don't know where do I trigger my PopulateProcess() method so that my combobox2 will be populated base on the selection of combobox1. Thanks for all the time and help! :)
--EDIT--
public class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public class Workcode
{
public int WorkcodeId { get; set; }
public string WorkcodeName { get; set; }
public Workcode(int id, string name)
{
WorkcodeId = id;
WorkcodeName = name;
}
}
initially the second combobox is empty and on select of the first combobox changed just pupulate the process
private int _workcodeId;
public int WorkcodeId
{
get { return _workcodeId; }
set
{
_workcodeId = value;
OnPropertyChanged("WorkcodeId");
if(WorkcodeID>0) PopulateProcess();
}
}
I can understand you want to have the next combobox to fill with data based on the previous value. Since i don't have classes of your type, i will give a simple example,
class ItemListViewModel<T> : INotifyPropertyChanged where T : class
{
private T _item;
private ObservableCollection<T> _items;
public ItemListViewModel()
{
_items = new ObservableCollection<T>();
_item = null;
}
public void SetItems(IEnumerable<T> items)
{
Items = new ObservableCollection<T>(items);
SelectedItem = null;
}
public ObservableCollection<T> Items
{
get { return _items; }
private set
{
_items = value;
RaisePropertyChanged("Items");
}
}
public T SelectedItem
{
get { return _item; }
set
{
_item = value;
RaisePropertyChanged("SelectedItem");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Then have the main viewmodel that will be bound to the DataContext of the view. Have the Load methods do what you want
class MyViewModel : INotifyPropertyChanged
{
public MyViewModel()
{
First = new ItemListViewModel<string>();
Second = new ItemListViewModel<string>();
Third = new ItemListViewModel<string>();
First.PropertyChanged += (s, e) => Update(e.PropertyName, First, Second, LoadSecond);
Second.PropertyChanged += (s, e) => Update(e.PropertyName, Second, Third, LoadThird);
LoadFirst();
}
public ItemListViewModel<string> First { get; set; }
public ItemListViewModel<string> Second { get; set; }
public ItemListViewModel<string> Third { get; set; }
private void LoadFirst()
{
First.SetItems(new List<string> { "One", "Two", "Three" });
}
private void LoadSecond()
{
Second.SetItems(new List<string> { "First", "Second", "Third" });
}
private void LoadThird()
{
Third.SetItems(new List<string> { "Firsty", "Secondly", "Thirdly" });
}
private void Update<T0, T1>(string propertyName, ItemListViewModel<T0> parent, ItemListViewModel<T1> child, Action loadAction)
where T0 : class
where T1 : class
{
if (propertyName == "SelectedItem")
{
if (parent.SelectedItem == null)
{
child.SetItems(Enumerable.Empty<T1>());
}
else
{
loadAction();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
In XAML,
<ComboBox ItemsSource="{Binding First.Items}" SelectedItem="{Binding First.SelectedItem}" />
<ComboBox ItemsSource="{Binding Second.Items}" SelectedItem="{Binding Second.SelectedItem}" />
<ComboBox ItemsSource="{Binding Third.Items}" SelectedItem="{Binding Third.SelectedItem}" />
The issue is here
<ComboBox Name="cmbWorkcode"
ItemsSource="{Binding Workcodes}"
DisplayMemberPath="WorkcodeName"
SelectedValuePath="WorkcodeId"
SelectedValue="{Binding Path=WorkcodeId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
It should be WorkcodeId instead of WorkcodeID. rest you can try as Nishanth replied
public int WorkcodeId
{
get { return _workcodeId; }
set
{
if(_workcodeId !=value)
{
_workcodeId = value;
OnPropertyChanged("WorkcodeId");
PopulateProcess();
}
}
}
I have ViewModel(implemented INotifyPropertyChanged) in the background and class Category which has only one property of type string. My ComboBox SelectedItem is bind to an instance of a Category. When i change the value of instance, SelectedItem is not being updated and Combobox is not changed.
EDIT: code
Combobox:
<ComboBox x:Name="categoryComboBox" Grid.Column="1" Grid.Row="3" Grid.ColumnSpan="2"
Margin="10" ItemsSource="{Binding Categories}"
DisplayMemberPath="Name" SelectedValue="{Binding NodeCategory, Mode=TwoWay}"/>
Property:
private Category _NodeCategory;
public Category NodeCategory
{
get
{
return _NodeCategory;
}
set
{
_NodeCategory = value;
OnPropertyChanged("NodeCategory");
}
}
[Serializable]
public class Category : INotifyPropertyChanged
{
private string _Name;
[XmlAttribute("Name")]
public string Name
{
get
{
return _Name;
}
set
{
_Name = value;
OnPropertyChanged("Name");
}
}
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
[field:NonSerialized]
public event PropertyChangedEventHandler PropertyChanged;
}
and what I am trying is: when I set
NodeCategory = some_list_of_other_objects.Category;
to have that item selected in Combobox with appropriate DisplayMemberPath
The category you are setting in this line -
NodeCategory = some_list_of_other_objects.Category;
and one present in your Categories collection(ItemsSource="{Binding Categories}") should be referring to same object. If they are not then SelectedItem won't work.
Solution 1 -
You can also try to use SelectedValuePath like this -
<ComboBox x:Name="categoryComboBox"
ItemsSource="{Binding Categories}"
DisplayMemberPath="Name"
SelectedValuePath="Name"
SelectedValue="{Binding NodeCategory, Mode=TwoWay}" />
and in code you can do something like this -
private string _NodeCategory;
public string NodeCategory
{
get
{
return _NodeCategory;
}
set
{
_NodeCategory = value;
OnPropertyChanged("NodeCategory");
}
}
and set selected item like this -
NodeCategory = some_list_of_other_objects.Category.Name;
and use selected value like this -
Category selectedCategory =
some_list_of_other_objects.FirstOrDefault(cat=> cat.Name == NodeCategory);
or
Category selectedCategory =
Categories.FirstOrDefault(cat=> cat.Name == NodeCategory);
Solution 2 -
Another possible solution can be -
NodeCategory =
Categories.FirstOrDefault(cat=> cat.Name == some_list_of_other_objects.Category.Name);
this way your NodeCategory property will have the reference of an object in Categories collection and SelectedItem will work.
Your XAML needs a couple of modifications but I think the real problem is with the code you have posted which I don't think is telling the full story.
For starters, your combobox ItemSource is bound to a property called Categories but you do not show how this property is coded or how your NodeCategory property is initially synced with the item.
Try using the following code and you will see that the selected item is kept in sync as the user changes the value in the combobox.
XAML
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<ComboBox x:Name="categoryComboBox"
Grid.Column="1"
Grid.Row="3"
Grid.ColumnSpan="2"
Margin="10"
ItemsSource="{Binding Categories}"
DisplayMemberPath="Name"
SelectedItem="{Binding NodeCategory}" />
<Label Content="{Binding NodeCategory.Name}" />
</StackPanel>
Code-behind
public partial class MainWindow : Window, INotifyPropertyChanged
{
private ObservableCollection<Category> _categories = new ObservableCollection<Category>
{
new Category { Name = "Squares"},
new Category { Name = "Triangles"},
new Category { Name = "Circles"},
};
public MainWindow()
{
InitializeComponent();
NodeCategory = _categories.First();
this.DataContext = this;
}
public IEnumerable<Category> Categories
{
get { return _categories; }
}
private Category _NodeCategory;
public Category NodeCategory
{
get
{
return _NodeCategory;
}
set
{
_NodeCategory = value;
OnPropertyChanged("NodeCategory");
}
}
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
[Serializable]
public class Category : INotifyPropertyChanged
{
private string _Name;
[XmlAttribute("Name")]
public string Name
{
get
{
return _Name;
}
set
{
_Name = value;
OnPropertyChanged("Name");
}
}
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
[field: NonSerialized]
public event PropertyChangedEventHandler PropertyChanged;
}
From my little example:
Note: This is setting just a string (or a category from another list), but the basics should be same here:
Basically this is done:
private void button1_Click(object sender, RoutedEventArgs e)
{
(this.DataContext as ComboBoxSampleViewModel).SelectCategory("Categorie 4");
}
Here is my XAML:
<Grid>
<ComboBox Height="23" HorizontalAlignment="Left" Margin="76,59,0,0"
Name="comboBox1" VerticalAlignment="Top" Width="120"
ItemsSource="{Binding List.Categories}"
DisplayMemberPath="Name"
SelectedValue="{Binding NodeCategory, Mode=TwoWay}" />
<Button Content="Button" Height="27" HorizontalAlignment="Left"
Margin="76,110,0,0" Name="button1" VerticalAlignment="Top"
Width="120" Click="button1_Click" />
</Grid>
and in the ViewModel of the Window
class ComboBoxSampleViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
public CategoryList List { get; set; }
public ComboBoxSampleViewModel()
{
this.List = new CategoryList();
NodeCategory = List.Selected;
}
private ComboBoxSampleItemViewModel nodeCategory;
public ComboBoxSampleItemViewModel NodeCategory
{
get
{
return nodeCategory;
}
set
{
nodeCategory = value;
NotifyPropertyChanged("NodeCategory");
}
}
internal void SelectCategory(string p)
{
this.List.SelectByName(p);
this.NodeCategory = this.List.Selected;
}
}
With the help of this little class:
public class CategoryList
{
public ObservableCollection<ComboBoxSampleItemViewModel> Categories { get; set; }
public ComboBoxSampleItemViewModel Selected { get; set; }
public CategoryList()
{
Categories = new ObservableCollection<ComboBoxSampleItemViewModel>();
var cat1 = new ComboBoxSampleItemViewModel() { Name = "Categorie 1" };
var cat2 = new ComboBoxSampleItemViewModel() { Name = "Categorie 2" };
var cat3 = new ComboBoxSampleItemViewModel() { Name = "Categorie 3" };
var cat4 = new ComboBoxSampleItemViewModel() { Name = "Categorie 4" };
Categories.Add(cat1);
Categories.Add(cat2);
Categories.Add(cat3);
Categories.Add(cat4);
this.Selected = cat3;
}
internal void SelectByName(string p)
{
this.Selected = this.Categories.Where(s => s.Name.Equals(p)).FirstOrDefault();
}
}
And this Item ViewModel
public class ComboBoxSampleItemViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
private string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
NotifyPropertyChanged("Name");
}
}
}
If Combobox is bound to object class of the View Model, while the SelectionBoxItem of the sender object (in the SelectionChanged in code behind) has not that type, it means it's still loading.
ComboBox combo = sender as ComboBox;
if (combo.SelectionBoxItem.GetType() == typeof(BindedClass))
{
// Not loading
}