ComboBox.SelectedValue не обновляется из источника привязки
-
05-07-2019 - |
Вопрос
Вот мой исходный объект привязки:
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.
- Это должно решить вашу проблему. У меня ушло больше недели, чтобы решить этот маленький фин. ха !! р>