ComboBox.SelectedValue не обновляется из источника привязки - PullRequest
25 голосов
/ 29 октября 2008

Вот мой объект привязки источника:

Public Class MyListObject

    Private _mylist As New ObservableCollection(Of String)
    Private _selectedName As String

    Public Sub New(ByVal nameList As List(Of String), ByVal defaultName As String)

        For Each name In nameList
            _mylist.Add(name)
        Next

        _selectedName = defaultName

    End Sub

    Public ReadOnly Property MyList() As ObservableCollection(Of String)
        Get
            Return _mylist
        End Get
    End Property

    Public ReadOnly Property SelectedName() As String
        Get
            Return _selectedName
        End Get
    End Property

End Class

Вот мой XAML:

<Window x:Class="Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300"
    xmlns:local="clr-namespace:WpfApplication1"
        >

    <Window.Resources>
        <ObjectDataProvider x:Key="MyListObject" ObjectInstance="" />
    </Window.Resources>

        <Grid>

        <ComboBox Height="23"
                  Margin="24,91,53,0"
                  Name="ComboBox1"
                  VerticalAlignment="Top"
                  SelectedValue="{Binding Path=SelectedName, Source={StaticResource MyListObject}, Mode=OneWay}"
                  ItemsSource="{Binding Path=MyList, Source={StaticResource MyListObject}, Mode=OneWay}"
                  />

        <Button Height="23"
                HorizontalAlignment="Left"
                Margin="47,0,0,87"
                Name="btn_List1"
                VerticalAlignment="Bottom"
                Width="75">List 1</Button>

        <Button Height="23"
                Margin="0,0,75,87"
                Name="btn_List2"
                VerticalAlignment="Bottom"
                HorizontalAlignment="Right"
                Width="75">List 2</Button>
    </Grid>
</Window>

Вот код позади:

Class Window1

    Private obj1 As MyListObject
    Private obj2 As MyListObject
    Private odp As ObjectDataProvider

    Public Sub New()

        InitializeComponent()

        Dim namelist1 As New List(Of String)
        namelist1.Add("Joe")
        namelist1.Add("Steve")
        obj1 = New MyListObject(namelist1, "Steve")
.
        Dim namelist2 As New List(Of String)
        namelist2.Add("Bob")
        namelist2.Add("Tim")
        obj2 = New MyListObject(namelist2, "Tim")

        odp = DirectCast(Me.FindResource("MyListObject"), ObjectDataProvider)
        odp.ObjectInstance = obj1

    End Sub

    Private Sub btn_List1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles btn_List1.Click

        odp.ObjectInstance = obj1

    End Sub

    Private Sub btn_List2_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles btn_List2.Click

        odp.ObjectInstance = obj2

    End Sub
End Class

Когда окно загружается в первый раз, привязки в порядке. ComboBox содержит имена «Джо» и «Стив» и «Стив» выбран по умолчанию. Однако когда я нажимаю кнопку, чтобы переключить ObjectInstance на obj2, ComSBox ItemsSource корректно заполняется в раскрывающемся списке, но для SelectedValue устанавливается значение Nothing вместо того, чтобы быть равным obj2.SelectedName.

Ответы [ 12 ]

31 голосов
/ 29 октября 2008

У нас была похожая проблема на прошлой неделе. Это связано с тем, как SelectedValue обновляет свои внутренние компоненты. Мы обнаружили, что если вы установите SelectedValue, он не увидит изменения, которое мы должны были установить вместо SelectedItem, который бы корректно обновлял все. Мой вывод таков: SelectedValue - это , предназначенное для операций get , а не установлено . Но это может быть просто ошибкой в ​​текущей версии 3.5sp1 .net

13 голосов
/ 21 июля 2010

Чтобы вызвать двухлетнюю беседу:

Другая возможность, если вы хотите использовать строки, - это связать ее со свойством Text поля со списком.

<ComboBox Text="{Binding Test}">
     <ComboBoxItem Content="A" />
     <ComboBoxItem Content="B" />
     <ComboBoxItem Content="C" />
</ComboBox>

Это связано с чем-то вроде:

public class TestCode
{
    private string _test;
    public string Test 
    { 
      get { return _test; }
      set
      {
         _test = value;
         NotifyPropertyChanged(() => Test); // NotifyPropertyChanged("Test"); if not using Caliburn
      }
    }
}

Приведенный выше код является двусторонним, поэтому, если вы установите Test = "B"; в коде поле со списком покажет «B», а затем, если вы выберете «A» из выпадающего списка, свойство связанным будет отражать изменение

8 голосов
/ 10 мая 2012

Использование

UpdateSourceTrigger=PropertyChanged 

в переплете

6 голосов
/ 13 мая 2011

Проблема:

Класс ComboBox ищет указанный объект с помощью метода IndexOf. Этот метод использует метод Equals для определения равенства.

Решение:

Итак, попробуйте установить SelectedIndex, используя SelectedValue через конвертер, как это:

C # код

//Converter

public class SelectedToIndexConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value != null && value is YourType)
            {
                YourType YourSelectedValue = (YourType) value;

                YourSelectedValue = (YourType) cmbDowntimeDictionary.Tag;
                YourType a = (from dd in Helper.YourType
                                        where dd.YourTypePrimaryKey == YourSelectedValue.YourTypePrimaryKey
                                        select dd).First();

                int index = YourTypeCollection.IndexOf(a); //YourTypeCollection - Same as ItemsSource of ComboBox
            }
            return null;
        }
         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value!=null && value is int)
            {
                return YourTypeCollection[(int) value];
            }

            return null;
        }
    }

Xaml

<ComboBox 
   ItemsSource="{Binding Source={StaticResource YourDataProvider}}"
   SelectedIndex="{Binding Path=YourValue, Mode=TwoWay, Converter={StaticResource SelectedToIndexConverter}, UpdateSourceTrigger=PropertyChanged}"/>

Удачи! :)

5 голосов
/ 21 апреля 2011

Типы SelectedValuePath и SelectedValue должны быть ТОЧНО одинаковыми.

Если, например, тип SelectedValuePath равен Int16, а тип свойства, связанного с SelectedValue, равен int, он не будет работать.

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

3 голосов
/ 07 августа 2009

Натолкнулся на нечто подобное, наконец, я просто подписался на событие SelectionChanged для выпадающего списка и установил для него свойство данных. Глупо и жаль, что это не нужно, но это сработало.

2 голосов
/ 12 августа 2009

Разумно ли установить SelectedValuePath = "Content" в xaml комбинированного списка, а затем использовать SelectedValue в качестве привязки?

Похоже, что у вас есть список строк, и вы хотите, чтобы привязка просто выполняла сопоставление строк с фактическим содержимым элемента в комбинированном списке, поэтому если вы укажете ему, какое свойство использовать для SelectedValue, оно должно работать; по крайней мере, это сработало для меня, когда я столкнулся с этой проблемой.

Кажется, что Content будет разумным значением по умолчанию для SelectedValue, но, возможно, это не так?

1 голос
/ 09 апреля 2019

В моем случае я связывался со списком, а я должен связываться со строкой.

Что я делал:

private ObservableCollection<string> _SelectedPartyType;

public ObservableCollection<string> SelectedPartyType { get { return 
_SelectedPartyType; } set { 
             _SelectedPartyType = value; OnPropertyChanged("SelectedPartyType"); } }

Что должно быть

 private string _SelectedPartyType;

 public string SelectedPartyType { get { return _SelectedPartyType; } set { 
             _SelectedPartyType = value; OnPropertyChanged("SelectedPartyType"); } }
1 голос
/ 07 февраля 2012

Вы пытались вызвать событие, которое сигнализирует, что SelectName обновлен, например, OnPropertyChanged ("SelectedName")? Это сработало для меня.

0 голосов
/ 14 декабря 2015

Только что решил это. Ха !!! Либо используйте [один из ...] .SelectedValue | .SelectedItem | .SelectedText Совет: Выбранное значение является предпочтительным для ComboStyle.DropDownList, тогда как .SelectedText для ComboStyle.DropDown.

- Это должно решить вашу проблему. У меня ушло больше недели, чтобы решить этот маленький фин. ха !!

...