ComboBox.SelectedValue не обновляется из источника привязки

StackOverflow https://stackoverflow.com/questions/247413

Вопрос

Вот мой исходный объект привязки:

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

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

Это было полезно?

Решение

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

Другие советы

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

Еще одна возможность, если вы хотите использовать строки, это связать их со свойством 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» из выпадающего списка, свойство связанным будет отражать изменение.

Использовать

UpdateSourceTrigger=PropertyChanged 

в привязке

Проблема:

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

Решение:

Итак, попробуйте установить SelectedIndex с помощью SelectedValue через Converter следующим образом:

код С#

//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;
        }
    }

Ксамл

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

Удачи!:)

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

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

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

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

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

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

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

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

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

Что я делал:

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"); } }

Режим привязки должен быть OneWayToSource или TwoWay, поскольку источник - это то, что вы хотите обновить. Режим OneWay является источником для цели и поэтому делает источник доступным только для чтения, в результате чего источник никогда не обновляется.

Вы знаете ... Я боролся с этой проблемой сегодня часами, и вы знаете, что я узнал? Это была проблема с DataType! Список, который заполнял ComboBox, был Int64, и я пытался сохранить значение в поле Int32! Не было выдано никаких ошибок, просто не сохранялись значения!

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top