Mismatch between RadComboBox's selected and displayed values when using a delayed PropertyChanged

1 posts, 0 answers
  1. Linus
    Linus avatar
    1 posts
    Member since:
    Feb 2015

    Posted 12 Feb 2015 Link to this post

    I'm trying to figure out why I'm experiencing a mismatch between the displayed and selected value in a RadComboBox.

    The below code is a shot at a minimal working example.

    If I place the cursor in the RadComboBox (dropdown closed) and press the down key a few times (quickly) the RadComboBox and TextBlock will show different values. From the looks of it the TextBlock is showing the correct value while the RadComboBox is not updating correctly.

    Why is this and how can I solve it?

    MainWindow.xaml
    <Window x:Class="RadComboBox1.MainWindow"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <StackPanel>
                <TextBlock Name="MyTextBlock" Text="{Binding SelectedItem.Name}"/>
                <telerik:RadComboBox
                    Name="MyRadComboBox"
                    ItemsSource="{Binding Items}"
                    SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
                    IsEditable="True"
                    DisplayMemberPath="Name"
                    CanAutocompleteSelectItems="False"
                    OpenDropDownOnFocus="True"
                    TextSearchMode="Contains"
                    IsFilteringEnabled="True">
                </telerik:RadComboBox>
            </StackPanel>
        </Grid>
    </Window>

    MainWindow.xaml.cs
    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Windows;
    using System.Windows.Threading;
     
    namespace RadComboBox1
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
     
                var dataContext = new RadComboBoxDataContext();
                MyRadComboBox.DataContext = dataContext;
                MyTextBlock.DataContext = dataContext;
            }
        }
     
        public class RadComboBoxItem
        {
            public string Name { get; set; }
        }
     
        public class RadComboBoxDataContext : INotifyPropertyChanged
        {
            public ObservableCollection<RadComboBoxItem> Items { get; set; }
     
            private RadComboBoxItem _selectedItem;
            public RadComboBoxItem SelectedItem
            {
                get
                {
                    var value = _selectedItem;
                    System.Diagnostics.Debug.WriteLine("GET=" + (value != null  ? value.Name : "<null>"));
                    return value;
                }
                set
                {
                    System.Diagnostics.Debug.WriteLine("SET=" + (value != null ? value.Name : "<null>"));
                    _nextSelectedItem = value;
                    _timer.Stop();
                    _timer.Start();
                }
            }
     
            private RadComboBoxItem _nextSelectedItem;
            private DispatcherTimer _timer;
     
            public RadComboBoxDataContext()
            {
                _timer = new DispatcherTimer();
                _timer.Interval = TimeSpan.FromMilliseconds(1000);
                _timer.Tick += OnTick;
     
                Items = new ObservableCollection<RadComboBoxItem>();
                for (var i = 0; i < 10; i++)
                {
                    Items.Add(new RadComboBoxItem { Name = "Item" + i});
                }
     
                SelectedItem = Items[0];
            }
     
            private void OnTick(object sender, EventArgs args)
            {
                _timer.Stop();
                _selectedItem = _nextSelectedItem;
                OnPropertyChanged("SelectedItem");
            }
     
            public event PropertyChangedEventHandler PropertyChanged;
     
            protected virtual void OnPropertyChanged(string propertyName = null)
            {
                PropertyChangedEventHandler handler = PropertyChanged;
                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }
    }
Back to Top