ComboBox.SelectedValue не обновляется из источника привязки
Здесь мой объект источника привязки:
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 содержит имена "Joe" и "Steve", а "Steve" выбран по умолчанию. Однако, когда я нажимаю кнопку, чтобы переключить ObjectInstance в obj2, ComboBox ItemsSource правильно заполняется в раскрывающемся списке, но в SelectedValue установлено значение Nothing вместо того, чтобы быть равно obj2.SelectedName.
Ответы
Ответ 1
У нас была аналогичная проблема на прошлой неделе. Это связано с тем, как SelectedValue
обновляет свои внутренние функции. Мы обнаружили, что если вы установите SelectedValue
, он не увидит изменения, которые мы должны были установить вместо SelectedItem
, которые должным образом обновили бы все. Я пришел к выводу, что SelectedValue
предназначен для операций, а не установлен. Но это может быть просто ошибкой в текущей версии 3.5sp1.net
Ответ 2
Чтобы разжечь двухлетний разговор:
Другая возможность, если вы хотите использовать строки, - привязать ее к свойству 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"; в коде, тогда combobox покажет "B", а затем, если вы выберете "A" из выпадающего списка, свойство bound будет отражать это изменение.
Ответ 3
Используйте
UpdateSourceTrigger=PropertyChanged
в привязке
Ответ 4
Проблема:
Класс 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;
}
}
Xaml
<ComboBox
ItemsSource="{Binding Source={StaticResource YourDataProvider}}"
SelectedIndex="{Binding Path=YourValue, Mode=TwoWay, Converter={StaticResource SelectedToIndexConverter}, UpdateSourceTrigger=PropertyChanged}"/>
Удачи!:)
Ответ 5
Тип SelectedValuePath
и SelectedValue
должен быть ТОЧНО одинаковым.
Если, например, тип SelectedValuePath
равен Int16
, а тип свойства, который привязан к SelectedValue
, равен int
, он не будет работать.
Я трачу часы, чтобы найти это, и вот почему я отвечаю здесь после того, как много времени задал вопрос. Возможно, это может показаться другим бедным парнем, похожим на меня с той же проблемой.
Ответ 6
Развернувшись во что-то подобное, я просто подписался на событие SelectionChanged для раскрывающегося списка и установил с ним свое свойство данных. Глупый и жаль, что он не нужен, но он сработал.
Ответ 7
Можно ли установить SelectedValuePath = "Content" в combobox xaml, а затем использовать SelectedValue в качестве привязки?
Кажется, что у вас есть список строк и вы хотите, чтобы привязка просто привязывала строку к фактическому содержимому элемента в combobox, поэтому, если вы сообщите, какое свойство использовать для SelectedValue, оно должно работать; по крайней мере, это сработало для меня, когда я столкнулся с этой проблемой.
Кажется, что Content был бы разумным дефолтом для SelectedValue, но, возможно, это не так?
Ответ 8
Вы пытались создать событие, которое сигнализирует SelectName, например, OnPropertyChanged ( "SelectedName" )? Это сработало для меня.
Ответ 9
Режим привязки должен быть OneWayToSource или TwoWay, поскольку источник - это то, что вы хотите обновить. Режим OneWay является источником для цели и, следовательно, делает Source ReadOnly, что приводит к тому, что никогда не обновляется Источник.
Ответ 10
Ты знаешь... Я борюсь с этой проблемой часами сегодня, и ты знаешь, что я узнал? Это проблема DataType! Список, заполняющий ComboBox, был Int64, и я пытался сохранить значение в поле Int32! Ошибок не было, они просто не сохраняли значения!
Ответ 11
Просто решил это. Ха!!!
Либо используйте [один из...].SelectedValue |.SelectedItem |.SelectedText
Совет. Выбранное значение предпочтительнее для ComboStyle.DropDownList, а .SelectedText для ComboStyle.DropDown.
-Это должно решить вашу проблему. заняло у меня больше недели, чтобы решить эту маленькую фэн. ха!!