Getting CRAZY with ComboBox SelectedItem!

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • DivinoZarathos
    New Member
    • Apr 2013
    • 1

    Getting CRAZY with ComboBox SelectedItem!

    I have a MVVM data-bound ComboBox that looks like this:

    Code:
        <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"/>
    Then, in my MainWindow.xaml .cs:

    Code:
        public MainWindow()
        {
            InitializeComponent();
            DataContext = m_ViewModel = new ViewModel();
        }
    
        private void ClickRefresh(Object sender, RoutedEventArgs e)
        {
            m_ViewModel.Populate();
        }
    Here is my ViewModel.cs:

    Code:
        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;
            }
        }
    And here is my ProcessInstance class relevant code:

    Code:
        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));
        }
    Now here is what happens... I start the application while no process instances exist:



    Then I open one or more process instances and I click the Refresh button. The first one is selected by ComboBox as default... I can keep that one selected or select another one, it doesn't matter:



    Now i close every process instance and I click Refresh button again. What happens in this case is that the Populate() method sets both SelectedItem and Items to null, so the ComboBox looks empty, and then it disables the ComboBox and makes the watermark Label visible. But here is what I get:



    The previous SelectedItem is still there. Why? WHY?!?!
    It's probably quite hard to understand what's going on with my code snippets, so if you want here is a link to download my project:

  • Sl1ver
    New Member
    • Mar 2009
    • 196

    #2
    Didn't read thoroughly but did you try two way binding? e.g Binding Path=this, Mode=TwoWay...?

    Comment

    Working...