ComboBox绑定到自定义ViewModel

我正在开发一个WPF项目。 这是我的XAML代码:

      

这是我的ViewModel代码:

 // BrowserInstance is a simple struct with two public fields: // 1) System.Diagnostics.Process Process // 2) System.String Name public sealed class BrowsersViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private BrowserInstance m_SelectedItem; public BrowserInstance SelectedItem { get { return m_SelectedItem; } set { if (m_SelectedItem != value) { m_SelectedItem = value; NotifyPropertyChanged("SelectedItem"); } } } private ObservableCollection m_Items; public ObservableCollection Items { get { return m_Items; } set { if (m_Items != value) { m_Items = value; NotifyPropertyChanged("Items"); } } } public BrowsersViewModel() { m_Items = new ObservableCollection(); Populate(); } private void NotifyPropertyChanged(String propertyName) { if (PropertyChanged != null) PropertyChanged(this, (new PropertyChangedEventArgs(propertyName))); } public void Populate() { foreach (Process process in Process.GetProcessesByName("chrome")) { BrowserInstance instance = new BrowserInstance(); instance.Process = process; instance.Name = "[Chrome] " + process.Handle.ToString() + " " + ((process.MainWindowTitle.Length > 0) ? process.MainWindowTitle : "NULL"); m_Items.Add(instance); } NotifyPropertyChanged("Items"); } } 

我真的很难让这个工作起来。 我到处都看过TONS的例子,我仍然无法找到让一切按预期工作的解决方案。

1)我在ComboBox下拉列表中看到很多值,但它们都是空的。 我想在ComboBox中显示BrowserInstance.Name属性,并在选择项目时检索BrowserInstance.Process值。

2)当应用程序启动时,将检查当前运行的浏览器进程以填充ComboBox。 如果没有找到正在运行的实例,我怎么能在我的ComboBox中显示一条消息,如“没有找到实例!”?

3)如果在应用程序统计信息中找到一个或多个浏览器实例,我如何默认选择第一个?

4)将使用Repopulate按钮以便用户重新检查正在运行的浏览器实例。 假设先前选择的实例仍在运行…如何保持选定的实例? 如果先前选择的实例不再运行,我如何再次默认选择第一个实例?

非常感谢!

编辑:这是我的当前代码

主窗口:

 public MainWindow() { InitializeComponent(); DataContext = m_BrowserInstances = new BrowserInstancesViewModel(); } private void OnClickButtonRefresh(Object sender, RoutedEventArgs e) { m_BrowserInstances.Populate(); } 

BrowserInstancesViewModel:

 public void Populate() { BrowserInstance selectedItem = m_SelectedItem; List items = new List(); foreach (Process process in Process.GetProcessesByName("chrome")) items.Add(new BrowserInstance(process)); if (items.Count > 0) { m_Items = new ObservableCollection(items.OrderBy(x => x.Process.Id)); if ((selectedItem != null) && (m_Items.SingleOrDefault(NewMethod(selectedItem)) != null)) m_SelectedItem = selectedItem; else m_SelectedItem = m_Items[0]; m_Enabled = true; } else { m_Items = new ObservableCollection() { (new BrowserInstance()) }; m_SelectedItem = m_Items[0]; m_Enabled = false; } NotifyPropertyChanged("Enabled"); NotifyPropertyChanged("Items"); NotifyPropertyChanged("SelectedItem"); } 

1)我无法复制这个问题,你确定有一个正在运行的chrome进程吗? :d

2)你可以像这样破解:D

            

或者更好的是你重新组合combobox以包含文本块并使用combobox的hasitems属性值绑定其可见性(当然你需要使用BoolToVis转换器)

3)在填充后将此代码添加到vm构造函数中

 if (m_Items.Count > 0) { SelectedItem = m_Items[0]; } 

4)将新的重新填充方法添加到vm并存储当前的选择项,填充,检查是否存在,重新选择项目

  public void Repopulate() { BrowserInstance currentSelectedItem = m_SelectedItem; Populate(); if (m_Items.Count>0) { if (currentSelectedItem !=null && m_Items.FirstOrDefault ((bi) => bi.Process == currentSelectedItem .Process) != null) { SelectedItem = currentSelectedItem; } else { SelectedItem = m_Items[0]; } } } 

注意:
当我尝试上面的代码并调试它我的chrome’进程列表不断变化时,我不确定要检查哪些属性来validation实例becoz的存在。 但基本上这就是你能做的

BrowserInstance是一个带有两个公共字段的简单结构:

WPF不支持数据绑定到字段。 只有属性。

这应该工作:

 public class BrowserInstance { public string Name { get; set; } public Process Process { get; set; } }