web-dev-qa-db-fra.com

ComboBox.SelectedValue ne se met pas à jour à partir de la source de liaison

Voici mon objet source de liaison:

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

Voici mon 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>

Voici le code-behind:

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

Lorsque la fenêtre se charge pour la première fois, les liaisons se connectent correctement. Le ComboBox contient les noms "Joe" et "Steve" et "Steve" est sélectionné par défaut. Cependant, lorsque je clique sur un bouton pour basculer l'ObjectInstance en obj2, le ComboBox ItemsSource est correctement rempli dans la liste déroulante, mais le SelectedValue est défini sur Nothing au lieu d'être égal à obj2.SelectedName.

25
Rob Sobers

Nous avons eu un problème similaire la semaine dernière. Cela a à voir avec la façon dont SelectedValue met à jour ses composants internes. Ce que nous avons trouvé, c'est que si vous définissez SelectedValue, il ne verrait pas le changement que nous devions plutôt définir SelectedItem qui mettrait à jour correctement tout. Ma conclusion est que SelectedValue est conçu pour get opérations et non défini. Mais cela peut juste être un bogue dans la version actuelle de 3.5sp1 .net

32
Aaron Fischer

Pour susciter une conversation de 2 ans:

Une autre possibilité, si vous souhaitez utiliser des chaînes, est de le lier à la propriété Text de la zone de liste déroulante.

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

Cela est lié à quelque chose comme:

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

Le code ci-dessus est bidirectionnel, donc si vous définissez Test = "B"; dans le code, la zone de liste déroulante affichera "B", puis si vous sélectionnez "A" dans la liste déroulante, la propriété liée reflétera le changement.

13
ASeale

Utilisation

UpdateSourceTrigger=PropertyChanged 

dans la reliure

8
Junier

Problème:

La classe ComboBox recherche l'objet spécifié à l'aide de la méthode IndexOf. Cette méthode utilise la méthode Equals pour déterminer l'égalité.

Solution:

Donc, essayez de définir SelectedIndex en utilisant SelectedValue via Converter comme ceci:

code 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}"/>

Bonne chance! :)

6
Pavel Kovalev

Le type de SelectedValuePath et de SelectedValue doit être EXACTEMENT le même.

Si, par exemple, le type de SelectedValuePath est Int16 et le type de la propriété qui se lie à SelectedValue est int cela ne fonctionnera pas.

Je passe des heures à trouver cela, et c'est pourquoi je réponds ici après tant de temps que la question a été posée. Peut-être qu'un autre pauvre gars comme moi avec le même problème peut le voir.

5
Dummy01

Ran dans quelque chose de similaire, enfin je viens de souscrire à l'événement SelectionChanged pour le menu déroulant et définir ma propriété de données avec elle. Idiot et j'aimerais que ce ne soit pas nécessaire, mais cela a fonctionné.

3
Alden Snow

Est-il raisonnable de définir SelectedValuePath = "Content" dans le xaml de la zone de liste déroulante, puis d'utiliser SelectedValue comme liaison?

Il semble que vous ayez une liste de chaînes et que vous vouliez que la liaison fasse juste la correspondance des chaînes avec le contenu réel de l'élément dans la zone de liste déroulante, donc si vous lui dites quelle propriété utiliser pour la SelectedValue, cela devrait fonctionner; au moins, cela a fonctionné pour moi lorsque j'ai rencontré ce problème.

Il semble que le contenu soit une valeur par défaut raisonnable pour SelectedValue, mais ce n'est peut-être pas le cas?

2
Mikeb

Avez-vous essayé de déclencher un événement signalant que SelectName a été mis à jour, par exemple, OnPropertyChanged ("SelectedName")? Cela a fonctionné pour moi.

1
davidinjc

Dans mon cas, j'étais lié à une liste alors que je devrais être lié à une chaîne.

Ce que je faisais:

private ObservableCollection<string> _SelectedPartyType;

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

ce qui devrait être

 private string _SelectedPartyType;

 public string SelectedPartyType { get { return _SelectedPartyType; } set { 
             _SelectedPartyType = value; OnPropertyChanged("SelectedPartyType"); } }
1
Rajon Tanducar

Vous savez ... Je me bats avec ce problème depuis des heures aujourd'hui, et vous savez ce que j'ai découvert? C'était un problème DataType! La liste qui remplissait le ComboBox était Int64, et j'essayais de stocker la valeur dans un champ Int32! Aucune erreur n'était lancée, elle ne stockait tout simplement pas les valeurs!

0
VBRocks

Je viens de résoudre cela. Huh !!! Utilisez soit [l'un des ...] .SelectedValue | .SelectedItem | Conseil .SelectedText: La valeur sélectionnée est préférée pour ComboStyle.DropDownList tandis que .SelectedText est pour ComboStyle.DropDown.

-Cela devrait résoudre votre problème. m'a pris plus d'une semaine pour résoudre cette petite fyn. hah !!

0
Sam Darteh

Le mode de liaison doit être OneWayToSource ou TwoWay car la source est celle que vous souhaitez mettre à jour. Le mode OneWay est de source à cible et rend donc la source en lecture seule, ce qui se traduit par ne jamais mettre à jour la source.

0
Chuck Borcher