2

I'm experiencing a refresh problem with my databound ComboBox. The selection is not refreshed when I change the SelectedValue from the code-behind. Here is a sample I made which illustrates the problem. Am I doing something wrong ?

Thanks !


<navigation:Page x:Class="Views.TestCB" 
           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
           xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
           xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
           mc:Ignorable="d"
           xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
           d:DesignWidth="640" d:DesignHeight="480"
           DataContext="{Binding RelativeSource={RelativeSource Self}}"
           Title="TestCB Page">
    <Grid x:Name="LayoutRoot">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <ComboBox ItemsSource="{Binding AllItems, Mode=TwoWay}" Grid.Row="0" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" DisplayMemberPath="Key" SelectedValuePath="Value" SelectedValue="{Binding SelectedValue, Mode=TwoWay}"/>
        <Button Content="Change" Click="Button_Click" Grid.Row="1" />
        <Button Content="Display" Click="Button_Click_1" Grid.Row="2" />
    </Grid>
</navigation:Page>

public partial class TestCB : Page, INotifyPropertyChanged
{
    public TestCB()
    {
        InitializeComponent();
    }

    private Random r = new Random();

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }

    private ObservableCollection<MyClass> allItemsField = new ObservableCollection<MyClass>();
    public ObservableCollection<MyClass> AllItems
    {
        get
        {
            return this.allItemsField;
        }

        set
        {
            if (this.allItemsField != value)
            {
                this.allItemsField = value;
                this.OnPropertyChanged("AllItems");
            }
        }
    }

    private MyClass selectedItemField = null;
    public MyClass SelectedItem
    {
        get
        {
            return this.selectedItemField;
        }

        set
        {
            if (this.selectedItemField != value)
            {
                this.selectedItemField = value;
                this.OnPropertyChanged("SelectedItem");
            }
        }
    }

    private int selectedValueField;
    public int SelectedValue
    {
        get
        {
            return this.selectedValueField;
        }

        set
        {
            if (this.selectedValueField != value)
            {
                this.selectedValueField = value;
                this.OnPropertyChanged("SelectedValue");
            }
        }
    }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        this.SetCombo();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        this.SetCombo();
        this.SelectRandom();
    }

    private void SetCombo()
    {
        this.AllItems.Clear();

        int generated = 0;
        while (generated < 10)
        {
            int val = r.Next(100);
            string key = string.Format("Key #{0}", val);

            if (!this.AllItems.Any(e => e.Key == key))
            {
                this.AllItems.Add(new MyClass { Key = key, Value = val });
                generated++;
            }
        }
    }

    private void SelectRandom()
    {
        var tmp = this.AllItems[r.Next(this.AllItems.Count)];
        this.SelectedValue = tmp.Value;
    }

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        MessageBox.Show(this.SelectedItem.Key);
    }
}

public class MyClass : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }

    private int valueField;
    public int Value
    {
        get
        {
            return this.valueField;
        }

        set
        {
            if (this.valueField != value)
            {
                this.valueField = value;
                this.OnPropertyChanged("Value");
            }
        }
    }

    private string keyField = string.Empty;
    public string Key
    {
        get
        {
            return this.keyField;
        }

        set
        {
            if (this.keyField != value)
            {
                this.keyField = value;
                this.OnPropertyChanged("Key");
            }
        }
    }
}

EDIT: Please note that in my program, the ComboBox is part of a ListBoxItem (the ListBox being also databound), so I can't access it directly to reset the binding/force a reload.

Shimrod
  • 3,115
  • 2
  • 36
  • 56

2 Answers2

2

I finally used the combobox found here : http://forums.lhotka.net/forums/p/9786/45971.aspx It corrected my SelectedValue binding problem.

Shimrod
  • 3,115
  • 2
  • 36
  • 56
0

Have you tried setting SelectedItem instead? SelectedValue has some know issues.

Community
  • 1
  • 1
decyclone
  • 30,394
  • 6
  • 63
  • 80
  • It doesn't seem to be a solution in my case. I the real application, there is a ListBox, and in each ListBoxItem is the combobox. Those comboboxes are bound to a collection in my code behind, and the selected value is a property of my object bound from the listbox. The problem is that the bound object only know an ID (int), which is a member of the objects in the collection, but not the whole object. I tried with a converter, but I can't access to the whole collection, and as I can't access the Combobox directly, I can't even read its ItemsSource... – Shimrod Feb 08 '11 at 09:10