2013-04-26 23 views
3

У меня есть данные связаны ComboBox который выглядит следующим образом:Получения CRAZY с ComboBox SelectedItem

<ComboBox Canvas.Left="5" Canvas.Top="5" IsEnabled="{Binding Path=ComboBoxEnabled}" ItemsSource="{Binding Path=Items}" SelectedItem="{Binding Mode=TwoWay, Path=SelectedItem}" Width="250"> 
    <ComboBox.ItemTemplate> 
     <DataTemplate> 
      <TextBlock MaxWidth="{Binding Path=ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ComboBox}}}" Text="{Binding}" TextTrimming="CharacterEllipsis"/> 
     </DataTemplate> 
    </ComboBox.ItemTemplate> 
</ComboBox> 
<Label Canvas.Left="5" Canvas.Top="4" TextOptions.TextFormattingMode="Display" Content="No process instances have been found." Height="{DynamicResource {x:Static SystemParameters.WindowCaptionHeightKey}}" IsEnabled="False" Visibility="{Binding Path=WatermarkVisibility}" Width="250"/> 
<Button Canvas.Right="5" Canvas.Top="5" Click="ClickRefresh" Content="Refresh" Width="75"/> 

Тогда в моем MainWindow.xaml.cs:

public MainWindow() 
{ 
    InitializeComponent(); 
    DataContext = m_ViewModel = new ViewModel(); 
} 

private void ClickRefresh(Object sender, RoutedEventArgs e) 
{ 
    m_ViewModel.Populate(); 
} 

Вот мой ViewModel.cs:

public ProcessInstance SelectedItem 
{ 
    get { return m_SelectedItem; } 
    set 
    { 
     if (m_SelectedItem != value) 
     { 
      m_SelectedItem = value; 
      NotifyPropertyChanged("SelectedItem"); 
     } 
    } 
} 

public ObservableCollection<ProcessInstance> Items 
{ 
    get { return m_Items; } 
    private set 
    { 
     if (m_Items != value) 
     { 
      m_Items = value; 
      NotifyPropertyChanged("Items"); 
     } 
    } 
} 

public ViewModel() 
{ 
    Populate(); 
} 

public void Populate() 
{ 
    ProcessInstance selectedItem = m_SelectedItem; 

    SelectedItem = null; 
    Items = null; 

    List<ProcessInstance> processInstances = new List<ProcessInstance>(); 

    foreach (Process process in Process.GetProcesses()) 
    { 
     if (...) 
      processInstances.Add(new ProcessInstance(process)); 
    } 

    if (processInstances.Count == 0) 
    { 
     ComboBoxEnabled = false; 
     WatermarkVisibility = Visibility.Visible; 
    } 
    else 
    { 
     Items = new ObservableCollection<ProcessInstance>(processInstances.OrderBy(x => x.Process.Id)); 

     if (selectedItem != null) 
      SelectedItem = m_Items.SingleOrDefault(x => x.ProcessEquals(selectedItem)); 

     if (m_SelectedItem == null) 
      SelectedItem = m_Items[0]; 

     ComboBoxEnabled = true; 
     WatermarkVisibility = Visibility.Hidden; 
    } 
} 

А вот мой класс ProcessInstance соответствующий код:

public override Boolean Equals(Object obj) 
{ 
    return Equals(obj as ProcessInstance); 
} 

public override Int32 GetHashCode() 
{ 
    Int32 hashCode; 

    if ((m_Process == null) || m_Process.HasExited) 
     hashCode = 0; 
    else 
    { 
     hashCode = (m_Process.Id.GetHashCode() * 397)^m_Process.MainModule.BaseAddress.GetHashCode(); 

     if (!String.IsNullOrEmpty(m_Process.MainWindowTitle)) 
      hashCode = (hashCode * 397)^m_Process.MainWindowTitle.GetHashCode(); 
    } 

    return hashCode; 
} 

public override String ToString() 
{ 
    String processId = process.Id.ToString("X8", CultureInfo.CurrentCulture); 
    String windowTitle = (process.MainWindowTitle.Length > 0) ? process.MainWindowTitle : "NULL"; 

    return String.Format(CultureInfo.CurrentCulture, "[{0}] {1} - {2}", type, processId, windowTitle); 
} 

public Boolean Equals(ProcessInstance other) 
{ 
    if (other == null) 
     return false; 

    if (ReferenceEquals(this, other)) 
     return true; 

    if (m_Process == null) 
    { 
     if (other.Process == null) 
      return true; 

     return false; 
    } 

    if (other.Process == null) 
     return false; 

    return ((m_Process.Id == other.Process.Id) && (m_Process.MainModule.BaseAddress == other.Process.MainModule.BaseAddress) && (m_Process.MainWindowTitle == other.Process.MainWindowTitle)); 
} 

public Boolean ProcessEquals(ProcessInstance other) 
{ 
    if (other == null) 
     throw new ArgumentNullException("other"); 

    if (m_Process == null) 
     return (other.Process == null); 

    if (other.Process == null) 
     return false; 

    return ((m_Process.Id == other.Process.Id) && (m_Process.MainModule.BaseAddress == other.Process.MainModule.BaseAddress)); 
} 

Теперь вот что происходит ... Я запустить приложение, а не экземпляры процесса не существует:

enter image description here

Тогда я открыть один или несколько экземпляров процесса, и я нажмите на кнопку Обновить. Первый один выбирается ComboBox по умолчанию ... Я могу держать, что один выбранный или выбрать другой, это не имеет значения:

enter image description here

Теперь я закрываю каждый экземпляр процесса, и я снова нажмите кнопку Обновить , Что происходит в этом случае, так это то, что метод Populate() устанавливает значение SelectedItem и Items равным null, поэтому ComboBox выглядит пустым, а затем отключает ComboBox и делает заметку с водяным знаком видимой. Но вот что я получаю:

enter image description here

Предыдущий SelectedItem еще есть. Зачем? ЗАЧЕМ?!?!

[EDIT] Вот ссылка загрузить проект:

http://www.filedropper.com/damncb

+0

где же текст «нет экземпляров процесса обнаружено не было» получить набор? –

+0

В XAML, Содержимое ярлыка = «Никаких экземпляров процесса не найдено». –

+0

'WatermarkVisibility' делает NotifyPropertyChanged? –

ответ

1

Я не могу запустить тестовый проект из-за версии, но я скопировал ViewModel класс и XAML на новый тестовый проект, и все это, кажется, работает, как ожидалось, с выбранным элементом очищаются, выпадающий отключение и водяной знак, появляющийся при нажатии кнопки.

Таким образом, я бы предположил, что что-то в вашей среде влияет на него, или это что-то еще, что не сразу видно с вашим кодом.

Чтобы узнать, в каком случае, я разместил (правильно работающий) код, который я использую для проверки ниже.

Если это не сработает, проблема имеет какое-то отношение к вашей среде. Я использую VS2010, .Net 4.0 и Windows 7.

Если это так, то у вас должно быть что-то, что происходит в другом месте вашего кода, что не сразу видно в ваших тестовых примерах. Я проверил бы любой асинхронный код, чтобы узнать, происходят ли уведомления PropertyChange в фоновом потоке, поскольку иногда это не вызывает обновление в потоке пользовательского интерфейса.

Я заранее извиняюсь за полученный код отвала :)

ViewModel класс был скопирован из тестового проекта и поиска/замены сделать, чтобы изменить "BrowserInstance" к «ViewModelBase», чтобы соответствовать мое приложение тестирования. Некоторые ненужные разделы также были слегка прокомментированы или изменены, чтобы разместить мое тестовое приложение.

public sealed class ViewModel : INotifyPropertyChanged 
{ 
    #region Members: Fields 
    private Boolean m_ButtonAttachEnabled; 
    private Boolean m_ButtonDetachEnabled; 
    private Boolean m_ButtonRefreshEnabled; 
    private Boolean m_ComboBoxEnabled; 
    private Boolean m_ProgressBarEnabled; 
    private ViewModelBase m_SelectedItem; 
    private Dictionary<String, PropertyChangedEventArgs> m_PropertyChangedEventArgs = new Dictionary<String, PropertyChangedEventArgs>(); 
    private Double m_ProgressBarMaximum; 
    private Double m_ProgressBarValue; 
    private IntPtr m_ProcessHandle; 
    private IntPtr m_ProcessHook; 
    private ObservableCollection<ViewModelBase> m_Items; 
    private Visibility m_WatermarkVisibility; 
    #endregion 

    #region Members: INotifyPropertyChanged 
    public event PropertyChangedEventHandler PropertyChanged; 
    #endregion 

    #region Properties 
    public Boolean ButtonAttachEnabled 
    { 
     get { return m_ButtonAttachEnabled; } 
     private set 
     { 
      if (m_ButtonAttachEnabled != value) 
      { 
       m_ButtonAttachEnabled = value; 
       NotifyPropertyChanged("ButtonAttachEnabled"); 
      } 
     } 
    } 

    public Boolean ButtonDetachEnabled 
    { 
     get { return m_ButtonDetachEnabled; } 
     private set 
     { 
      if (m_ButtonDetachEnabled != value) 
      { 
       m_ButtonDetachEnabled = value; 
       NotifyPropertyChanged("ButtonDetachEnabled"); 
      } 
     } 
    } 

    public Boolean ButtonRefreshEnabled 
    { 
     get { return m_ButtonRefreshEnabled; } 
     private set 
     { 
      if (m_ButtonRefreshEnabled != value) 
      { 
       m_ButtonRefreshEnabled = value; 
       NotifyPropertyChanged("ButtonRefreshEnabled"); 
      } 
     } 
    } 

    public Boolean ComboBoxEnabled 
    { 
     get { return m_ComboBoxEnabled; } 
     private set 
     { 
      if (m_ComboBoxEnabled != value) 
      { 
       m_ComboBoxEnabled = value; 
       NotifyPropertyChanged("ComboBoxEnabled"); 
      } 
     } 
    } 

    public Boolean ProgressBarEnabled 
    { 
     get { return m_ProgressBarEnabled; } 
     private set 
     { 
      if (m_ProgressBarEnabled != value) 
      { 
       m_ProgressBarEnabled = value; 
       NotifyPropertyChanged("ProgressBarEnabled"); 
      } 
     } 
    } 

    public ViewModelBase SelectedItem 
    { 
     get { return m_SelectedItem; } 
     set 
     { 
      if (m_SelectedItem != value) 
      { 
       m_SelectedItem = value; 
       NotifyPropertyChanged("SelectedItem"); 
      } 
     } 
    } 

    public Double ProgressBarMaximum 
    { 
     get { return m_ProgressBarMaximum; } 
     private set 
     { 
      if (m_ProgressBarMaximum != value) 
      { 
       m_ProgressBarMaximum = value; 
       NotifyPropertyChanged("ProgressBarMaximum"); 
      } 
     } 
    } 

    public Double ProgressBarValue 
    { 
     get { return m_ProgressBarValue; } 
     private set 
     { 
      if (m_ProgressBarValue != value) 
      { 
       m_ProgressBarValue = value; 
       NotifyPropertyChanged("ProgressBarValue"); 
      } 
     } 
    } 

    public ObservableCollection<ViewModelBase> Items 
    { 
     get { return m_Items; } 
     private set 
     { 
      if (m_Items != value) 
      { 
       m_Items = value; 
       NotifyPropertyChanged("Items"); 
      } 
     } 
    } 

    public Visibility WatermarkVisibility 
    { 
     get { return m_WatermarkVisibility; } 
     private set 
     { 
      if (m_WatermarkVisibility != value) 
      { 
       m_WatermarkVisibility = value; 
       NotifyPropertyChanged("WatermarkVisibility"); 
      } 
     } 
    } 
    #endregion 

    #region Constructors 
    public ViewModel() 
    { 
     m_PropertyChangedEventArgs = new Dictionary<String, PropertyChangedEventArgs>(); 
     Populate(); 
    } 
    #endregion 

    #region Methods: Functions 
    private PropertyChangedEventArgs GetPropertyChangedEventArgs(String propertyName) 
    { 
     PropertyChangedEventArgs propertyChangedEventArgs; 

     if (!m_PropertyChangedEventArgs.TryGetValue(propertyName, out propertyChangedEventArgs)) 
      m_PropertyChangedEventArgs[propertyName] = propertyChangedEventArgs = new PropertyChangedEventArgs(propertyName); 

     return propertyChangedEventArgs; 
    } 

    private void NotifyPropertyChanged(String propertyName) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, GetPropertyChangedEventArgs(propertyName)); 
    } 

    private void ResetProgressBar(Int32 maximumValue = 100) 
    { 
     ProgressBarMaximum = maximumValue; 
     ProgressBarValue = 0; 
    } 

    private void SetInterfaceStatus(Status status) 
    { 
     switch (status) 
     { 
      case Status.Attached: 
       { 
        ButtonAttachEnabled = false; 
        ButtonDetachEnabled = true; 
        ButtonRefreshEnabled = false; 
        ComboBoxEnabled = false; 
        ProgressBarEnabled = false; 
        WatermarkVisibility = Visibility.Hidden; 

        break; 
       } 

      case Status.Busy: 
       { 
        ButtonAttachEnabled = false; 
        ButtonDetachEnabled = false; 
        ButtonRefreshEnabled = false; 
        ComboBoxEnabled = false; 
        ProgressBarEnabled = true; 
        WatermarkVisibility = Visibility.Hidden; 

        break; 
       } 

      case Status.Detached: 
       { 
        ButtonAttachEnabled = true; 
        ButtonDetachEnabled = false; 
        ButtonRefreshEnabled = true; 
        ComboBoxEnabled = true; 
        ProgressBarEnabled = true; 
        WatermarkVisibility = Visibility.Hidden; 

        goto default; 
       } 

      case Status.DetachedEmpty: 
       { 
        ButtonAttachEnabled = false; 
        ButtonDetachEnabled = false; 
        ButtonRefreshEnabled = true; 
        ComboBoxEnabled = false; 
        ProgressBarEnabled = false; 
        WatermarkVisibility = Visibility.Visible; 

        goto default; 
       } 

      default: 
       ResetProgressBar(); 
       break; 
     } 
    } 

    public void Attach() 
    { 
    } 

    public void Detach() 
    { 
    } 

    public void Populate() 
    { 
     ViewModelBase selectedItem = m_SelectedItem; 

     SelectedItem = null; 
     Items = new ObservableCollection<ViewModelBase>(); 

     List<ViewModelBase> ViewModelBases = new List<ViewModelBase>(); 

     if (selectedItem == null) 
     { 
      ViewModelBases.Add(new Test { TestValue = "123456789", TestEnum = TestEnum.A, TestBool = false, TestBool2 = true }); 
      ViewModelBases.Add(new Test { TestValue = "987365321", TestEnum = TestEnum.B, TestBool = true, TestBool2 = true }); 
      ViewModelBases.Add(new Test { TestValue = "784512457", TestEnum = TestEnum.B, TestBool = true, TestBool2 = true }); 
     } 

     //foreach (Process process in Process.GetProcesses()) 
     //{ 
     // if ((process.ProcessName == "chrome") && !process.HasExited && (process.MainModule.ModuleName == "chrome.exe")) 
     //  ViewModelBases.Add(new ViewModelBase(ViewModelBaseType.Chrome, process)); 
     //} 

     if (ViewModelBases.Count == 0) 
      SetInterfaceStatus(Status.DetachedEmpty); 
     else 
     { 
      Items = new ObservableCollection<ViewModelBase>(ViewModelBases); 

      if (selectedItem != null) 
       SelectedItem = m_Items.SingleOrDefault(x => x.Equals(selectedItem)); 

      if (m_SelectedItem == null) 
       SelectedItem = m_Items[0]; 

      SetInterfaceStatus(Status.Detached); 
     } 
    } 
    #endregion 

    #region Enumerators 
    private enum Status 
    { 
     Attached, 
     Busy, 
     Detached, 
     DetachedEmpty 
    } 
    #endregion 
} 

ViewModelBase класс от моего тестового приложения выглядит следующим образом:

public class ViewModelBase : INotifyPropertyChanged, IDataErrorInfo 
{ 
    // Fields 
    private PropertyChangedEventHandler propertyChanged; 

    // Events 
    public event PropertyChangedEventHandler PropertyChanged 
    { 
     add 
     { 
      PropertyChangedEventHandler handler2; 
      PropertyChangedEventHandler propertyChanged = this.propertyChanged; 
      do 
      { 
       handler2 = propertyChanged; 
       PropertyChangedEventHandler handler3 = (PropertyChangedEventHandler)Delegate.Combine(handler2, value); 
       propertyChanged = Interlocked.CompareExchange<PropertyChangedEventHandler>(ref this.propertyChanged, handler3, handler2); 
      } 
      while (propertyChanged != handler2); 
     } 
     remove 
     { 
      PropertyChangedEventHandler handler2; 
      PropertyChangedEventHandler propertyChanged = this.propertyChanged; 
      do 
      { 
       handler2 = propertyChanged; 
       PropertyChangedEventHandler handler3 = (PropertyChangedEventHandler)Delegate.Remove(handler2, value); 
       propertyChanged = Interlocked.CompareExchange<PropertyChangedEventHandler>(ref this.propertyChanged, handler3, handler2); 
      } 
      while (propertyChanged != handler2); 
     } 
    } 

    protected void RaisePropertyChanged(params string[] propertyNames) 
    { 
     if (propertyNames == null) 
     { 
      throw new ArgumentNullException("propertyNames"); 
     } 
     foreach (string str in propertyNames) 
     { 
      this.RaisePropertyChanged(str); 
     } 
    } 

    protected void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression) 
    { 
     string propertyName = PropertySupport.ExtractPropertyName<T>(propertyExpression); 
     this.RaisePropertyChanged(propertyName); 
    } 

    protected virtual void RaisePropertyChanged(string propertyName) 
    { 
     PropertyChangedEventHandler propertyChanged = this.propertyChanged; 
     if (propertyChanged != null) 
     { 
      propertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    #region IDataErrorInfo & Validation Members 

    /// <summary> 
    /// List of Property Names that should be validated 
    /// </summary> 
    //protected List<string> ValidatedProperties = new List<string>(); 


    #region Validation Delegate 

    public delegate string ValidationDelegate(
     object sender, string propertyName); 

    private List<ValidationDelegate> _validationDelegates = 
     new List<ValidationDelegate>(); 

    public void AddValidationDelegate(ValidationDelegate func) 
    { 
     _validationDelegates.Add(func); 
    } 

    public void RemoveValidationDelegate(ValidationDelegate func) 
    { 
     if (_validationDelegates.Contains(func)) 
      _validationDelegates.Remove(func); 
    } 

    #endregion // Validation Delegate 


    public virtual string GetValidationError(string propertyName) 
    { 
     // If user specified properties to validate, check to see if this one exists in the list 
     //if (ValidatedProperties.IndexOf(propertyName) < 0) 
     //{ 
     // return null; 
     //} 

     string s = null; 

     //switch (propertyName) 
     //{ 

     //} 

     foreach (var func in _validationDelegates) 
     { 
      s = func(this, propertyName); 
      if (s != null) 
       return s; 
     } 


     return s; 
    } 

    string IDataErrorInfo.Error { get { return null; } } 

    string IDataErrorInfo.this[string propertyName] 
    { 
     get { return this.GetValidationError(propertyName); } 
    } 

    //public bool IsValid 
    //{ 
    // get 
    // { 
    //  return (GetValidationError() == null); 
    // } 
    //} 

    //public string GetValidationError() 
    //{ 
    // string error = null; 

    // if (ValidatedProperties != null) 
    // { 
    //  foreach (string s in ValidatedProperties) 
    //  { 
    //   error = GetValidationError(s); 
    //   if (error != null) 
    //   { 
    //    return error; 
    //   } 
    //  } 
    // } 

    // return error; 
    //} 

    #endregion // IDataErrorInfo & Validation Members 
} 

И Test класс для тестирования заключается в следующем:

public class Test : ViewModelBase 
{ 
    public int Id { get; set; } 
    private TestEnum _testEnum; 
    private string _testValue = "Testing"; 
    private double _testNumber = 10000; 
    private bool _testBool; 
    private bool _testBool2; 

    private ObservableCollection<int> _someCollection; 

    public ObservableCollection<int> SomeCollection 
    { 
     get 
     { 
      if (_someCollection == null) 
       _someCollection = new ObservableCollection<int>(); 

      return _someCollection; 
     } 
    } 

    public Test() 
    { 
     //this.ValidatedProperties.Add("TestValue"); 
     //this.ValidatedProperties.Add("TestNumber"); 

     SomeCollection.Add(1); 
     SomeCollection.Add(2); 
     SomeCollection.Add(3); 
    } 

    public override string ToString() 
    { 
     return TestValue; 
    } 


    public void RaisePropertyChanged1(string property) 
    { 
     base.RaisePropertyChanged(property); 
    } 

    //public override string GetValidationError(string propertyName) 
    //{ 

    // // If user specified properties to validate, check to see if this one exists in the list 
    // if (ValidatedProperties.IndexOf(propertyName) < 0) 
    // { 
    //  return null; 
    // } 

    // string s = base.GetValidationError(propertyName); ; 

    // switch (propertyName) 
    // { 
    //  case "TestValue": 
    //   s = "error"; 
    //   break; 
    // } 

    // return s; 

    //} 



    public TestEnum TestEnum 
    { 
     get { return _testEnum; } 
     set 
     { 
      if (value != _testEnum) 
      { 
       _testEnum = value; 
       base.RaisePropertyChanged(() => this.TestEnum); 
      } 
     } 
    } 

    private ObservableCollection<int> _test; 

    public ObservableCollection<int> Test1 
    { 
     get 
     { 
      if (_test == null) 
      { 
       _test = new ObservableCollection<int>(); 
       for (int i = 0; i < 5; i++) 
       { 
        _test.Add(i); 
       } 
      } 
      return _test; 
     } 
     set 
     { 
      if (value != _test) 
      { 
       _test = value; 
       RaisePropertyChanged(() => this.Test1); 
      } 
     } 
    } 

    public string TestValue 
    { 
     get { return _testValue; } 
     set 
     { 
      if (value != _testValue) 
      { 
       _testValue = value; 
       base.RaisePropertyChanged(() => this.TestValue); 
      } 
     } 
    } 

    public bool TestBool 
    { 
     get { return _testBool; } 
     set 
     { 
      if (value != _testBool) 
      { 
       _testBool = value; 
       base.RaisePropertyChanged(() => this.TestBool); 
      } 
     } 
    } 

    public bool TestBool2 
    { 
     get { return _testBool2; } 
     set 
     { 
      if (value != _testBool2) 
      { 
       _testBool2 = value; 
       base.RaisePropertyChanged(() => this.TestBool); 
      } 
     } 
    } 

    public double TestNumber 
    { 
     get { return _testNumber; } 
     set 
     { 
      if (value != _testNumber) 
      { 
       _testNumber = value; 
       base.RaisePropertyChanged(() => this.TestNumber); 
      } 
     } 
    } 
} 

Мой тест XAML смотрели, как это. Я добавил минимальную высоту, потому что она не отображалась правильно с моими стилями тестирования, и был добавлен фоновый цвет, чтобы увидеть, где он был рендеринг.

<Grid MinHeight="100" Background="Lavender"> 
    <Canvas Background="Red"> 
     <GroupBox Canvas.Left="10" Canvas.Top="5" BorderBrush="Black" Header="Test" Height="86" Width="472"> 
      <Canvas> 
       <ComboBox Canvas.Left="5" Canvas.Top="5" IsEnabled="{Binding Path=ComboBoxEnabled}" ItemsSource="{Binding Path=Items}" SelectedItem="{Binding Mode=TwoWay, Path=SelectedItem}" Width="366"> 
        <ComboBox.ItemTemplate> 
         <DataTemplate> 
          <TextBlock MaxWidth="{Binding Path=ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ComboBox}}}" Text="{Binding }" TextTrimming="CharacterEllipsis"/> 
         </DataTemplate> 
        </ComboBox.ItemTemplate> 
       </ComboBox> 
       <Label Canvas.Left="5" Canvas.Top="4" TextOptions.TextFormattingMode="Display" Content="This is a Test" Height="50" IsEnabled="False" Visibility="{Binding Path=WatermarkVisibility}" Width="366"/> 
       <Button Canvas.Right="5" Canvas.Top="5" Click="Button_Click_1" Content="Refresh" IsEnabled="{Binding Path=ButtonRefreshEnabled}" Width="75"/> 
      </Canvas> 
     </GroupBox> 
    </Canvas> 
</Grid> 

И в последнюю очередь, код позади моего XAML:

ViewModel m_ViewModel; 

public MainWindow() 
{ 
    InitializeComponent(); 
    DataContext = m_ViewModel = new ViewModel(); 
} 

private void Button_Click_1(object sender, RoutedEventArgs e) 
{ 
    m_ViewModel.Populate(); 
} 
+0

У меня тяжелые времена, когда я понял, что вы изменили и что изменилось в глобальном поведении. Во всяком случае, я скоро проверю это! Большое спасибо! –

+0

@ Zarathos Дайте мне знать, как это происходит. Мне это интересно. Для вашего тестового проекта я в значительной степени копировал/вставлял класс ViewModel и XAML (включая код) в свой тестовый проект, а затем немного изменили их, чтобы изменить/закомментировать части, которые, как представляется, не связаны с проблемой, и которые ссылаются на другие области вашего приложения. Класс 'ViewModelBase' и' Test' уже существовал в моем тестовом проекте, поэтому я просто заменил его для класса «BrowserInstance». Я не смотрел ни на один из других файлов в тестовом приложении. – Rachel

+1

Хорошо, что ваша реализация сработала ... тогда я нашел способ исправить мой на основе некоторого журнала отладки ... Это была плохая реализация BrowserInstance IEquatable, которая по какой-то причине не вызывает плохого поведения в вашем проекте! –

1

Вы не очистив ObservableCollection. Попробуйте это:

if (processInstances.Count == 0) 
{ 
    Items.Clear(); 

    // remaining of your logic; 
} 
+0

Я не очищаю его, но я установил его в null в начале метода ViewModel.Populate(). Во всяком случае, я пробовал, но это не работает. –

+0

Я приложил свой исходный код проекта, если вы хотите попробовать. Он немного изменен, но ошибка все еще остается. –

3

Вы должны очистить SelectedValue собственности на ComboBox, или, может быть установлен SelectedIndex -1

+0

Значит, мне тоже нужно связать это свойство? –

+0

Или привязаться к нему вместо –

+0

Вы имеете в виду, что я должен заменить привязку SelectedItem с помощью TwoWay SelectedValue? –

1

Несколько точек ударить раствора

  1. Попробуйте очистить значения вместо аннулирование их, так что элементы интерфейса WPF не потеряли бы привязки к экземпляру при возникновении событий PropertyChanged.
  2. На основании пункта 1 установите значение SelectedItem для значения '' для свойства Text или всего, что вы завернули, вместо того, чтобы сбрасывать весь экземпляр и обновлять каждый раз.
  3. Хм .. Вы не показали, как combobox.selectedItem получает ToString() или что-то подобное из класса-обертки ProcessInstance, поэтому я не мог опубликовать изменение логики с точки зрения кода.
+0

Я добавил переопределение ToString() моего ProcessInstance, редактирующего мой вопрос. вторая точка, хотя ... –

+0

ok Я предполагаю, что вы могли бы обнулить внутренний объект _process, а 'ToString()' должен возвращать '', когда _process является нулевым. –

+0

Попытка ... но даже если ComboBox пуст, SelectedItem все еще там , и это не пусто. Я прикрепил исходный код проекта, если вы хотите попробовать. Он слегка изменен но ошибка все еще остается. –