0

I have a window with a combobox. This comboboxhas 5 ComboboxItems.

I binding the SelectedItem (combobox) to the ComboBoxSelectedIndex Property in my code behind file.

In the example I want that it is not possible to select the items 4 and 5.

But i can select the item 4 and 5. What's wrong?

xaml code:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        WindowStartupLocation="CenterScreen"
        Height="350"
        Width="500">
    <StackPanel VerticalAlignment="Center">
        <ComboBox SelectedIndex="{Binding Path=ComboBoxSelectedIndex, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
            <ComboBoxItem>Item 1</ComboBoxItem>
            <ComboBoxItem>Item 2</ComboBoxItem>
            <ComboBoxItem>Item 3</ComboBoxItem>
            <ComboBoxItem>Item 4</ComboBoxItem>
            <ComboBoxItem>Item 5</ComboBoxItem>
        </ComboBox>     
    </StackPanel>
</Window>

codebehind file:

namespace WpfApplication1
{
    public partial class MainWindow : INotifyPropertyChanged
    {
        private int _selectedIndex;

        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
        }

        public int ComboBoxSelectedIndex
        {
            get { return _selectedIndex; }
            set
            {
                if (value < 3)
                {
                    _selectedIndex = value;
                }
                OnPropertyChanged("ComboBoxSelectedIndex");
                Trace.WriteLine(ComboBoxSelectedIndex);
            }
        }

        #region Implementation of INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
    }
}

(I am aware that I can solve this problem with the property Is Enabled. But I don't what that here)

David
  • 4,027
  • 10
  • 50
  • 102

3 Answers3

0

What happens is:

  • you select an item.
  • binding makes a call to MainWindow.SelectedIndex.set()
  • OnPropertyChanged indicates a change of the property... but WPF is already setting this property, so the information is dismissed.

This is a very painful problem of WPF binding... What you could do is wait for WPF to finish setting the property in the combobox and then trigger the NotifyPropertyChange. This can be done creating a new thread in the setter to notify back in the dispatcher thread.

I have had this problem a lot and finished binding both SelectedItem and SelectedIndex... getting often lost between both :(

Kek
  • 3,145
  • 2
  • 20
  • 26
  • I ve never had that problem. Just bind to SelectedItem there was never anything dismissed. Another possibilty would be to bind the itemssource to a http://msdn.microsoft.com/de-de/library/system.windows.data.collectionview.aspx and so the collectionview would contain the selecteditem automatically see http://msdn.microsoft.com/de-de/library/system.windows.data.collectionview.currentitem.aspx – Florian Aug 10 '12 at 07:16
0

Create your custom combobox to implement this

<StackPanel Orientation="Vertical">
    <wpfProj:ExtendedCombobBox 
       SelectedIndex="{Binding Path=ComboBoxSelectedIndex, 
                              Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
       MaxSelectedIndex="{Binding Path=MaxSelectedIndex}">
        <ComboBoxItem>Item 1</ComboBoxItem>
        <ComboBoxItem>Item 2</ComboBoxItem>
        <ComboBoxItem>Item 3</ComboBoxItem>
        <ComboBoxItem>Item 4</ComboBoxItem>
        <ComboBoxItem>Item 5</ComboBoxItem>
    </wpfProj:ExtendedCombobBox>
</StackPanel>

And code the custom combobox

public class ExtendedCombobBox:ComboBox
{
    public static readonly DependencyProperty MaxSelectedIndexProperty =
        DependencyProperty.Register("MaxSelectedIndex", typeof (int), typeof (ExtendedCombobBox), new PropertyMetadata(default(int)));

    public int MaxSelectedIndex
    {
        get { return (int) GetValue(MaxSelectedIndexProperty); }
        set { SetValue(MaxSelectedIndexProperty, value); }
    }

    protected override void OnSelectionChanged(SelectionChangedEventArgs e)
    {
        if (Items.IndexOf(e.AddedItems[0]) > MaxSelectedIndex)
            e.Handled = true;
        else
            base.OnSelectionChanged(e);
    }
}

UPD1. Or you can just use standard one and subscribe to the SelectionChanged event. But I'd prefer to use custombobox.

Artiom
  • 7,694
  • 3
  • 38
  • 45
0

The return value isn't a int32 but a string.

public string ComboBoxSelectedIndex
    {
        get { return _selectedIndex; }
        set
        {
            if (int.parse(value) < 3)
            {
                _selectedIndex = value;
            }
            OnPropertyChanged("ComboBoxSelectedIndex");
            Trace.WriteLine(ComboBoxSelectedIndex);
        }
    }