WPF – MVVM – ComboBox SelectedItem
我在后台和类Category
有ViewModel
(实现了INotifyPropertyChanged
),它只有一个string
类型的属性。 我的ComboBox SelectedItem绑定到Category的实例。 当我更改实例的值时,SelectedItem没有被更新,并且Combobox没有被更改。
编辑:代码
combobox:
属性:
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; }
而我正在尝试的是:当我设置
NodeCategory = some_list_of_other_objects.Category;
使用适当的DisplayMemberPath
在Combobox
选择该项目
您在此行中设置的类别 –
NodeCategory = some_list_of_other_objects.Category;
您的Categories集合中存在的一个( ItemsSource="{Binding Categories}"
)应该指向同一个对象。 如果它们不是那么SelectedItem
将无法工作。
解决方案1 –
你也可以尝试像这样使用SelectedValuePath
–
在代码中你可以做这样的事情 –
private string _NodeCategory; public string NodeCategory { get { return _NodeCategory; } set { _NodeCategory = value; OnPropertyChanged("NodeCategory"); } }
并设置这样的选定项目 –
NodeCategory = some_list_of_other_objects.Category.Name;
并使用这样的选定值 –
Category selectedCategory = some_list_of_other_objects.FirstOrDefault(cat=> cat.Name == NodeCategory);
要么
Category selectedCategory = Categories.FirstOrDefault(cat=> cat.Name == NodeCategory);
解决方案2 –
另一个可能的解决方案是 –
NodeCategory = Categories.FirstOrDefault(cat=> cat.Name == some_list_of_other_objects.Category.Name);
这样,您的NodeCategory属性将具有Categories集合中对象的引用,并且SelectedItem
将起作用。
您的XAML需要进行一些修改,但我认为真正的问题在于您发布的代码,我认为这些代码并不能完整地讲述。 对于初学者,您的comboboxItemSource
绑定到名为Categories的属性,但您不显示此属性的编码方式或NodeCategory
属性最初如何与项同步。
尝试使用以下代码,当用户更改combobox中的值时,您将看到所选项目保持同步。
XAML
代码隐藏
public partial class MainWindow : Window, INotifyPropertyChanged { private ObservableCollection _categories = new ObservableCollection { new Category { Name = "Squares"}, new Category { Name = "Triangles"}, new Category { Name = "Circles"}, }; public MainWindow() { InitializeComponent(); NodeCategory = _categories.First(); this.DataContext = this; } public IEnumerable 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; }
从我的小例子:
注意:这只是设置一个字符串(或另一个列表中的类别),但基础知识应该相同:
基本上这样做:
private void button1_Click(object sender, RoutedEventArgs e) { (this.DataContext as ComboBoxSampleViewModel).SelectCategory("Categorie 4"); }
这是我的XAML:
并在Window的ViewModel中
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; } }
在这个小class的帮助下:
public class CategoryList { public ObservableCollection Categories { get; set; } public ComboBoxSampleItemViewModel Selected { get; set; } public CategoryList() { Categories = new ObservableCollection (); 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(); } }
而这个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"); } } }