web-dev-qa-db-ja.com

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はobj2.SelectedNameと等しくなる代わりにNothingに設定されます。

25
Rob Sobers

先週も同様の問題がありました。 SelectedValueが内部を更新する方法に関係しています。私たちが見つけたのは、SelectedValueを設定すると、代わりにSelectedItemを設定する必要がある変更が表示されず、すべてが正しく更新されるということです。私の結論は、SelectedValueget用に設計された操作であり、設定されていないです。しかし、これは3.5sp1 .netの現在のバージョンのバグにすぎない可能性があります

32
Aaron Fischer

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"を設定すると、コードでは、コンボボックスに「B」が表示され、ドロップダウンから「A」を選択すると、バインドされたプロパティに変更が反映されます。

13
ASeale

使用する

UpdateSourceTrigger=PropertyChanged 

バインディングで

8
Junier

問題:

ComboBoxクラスは、IndexOfメソッドを使用して、指定されたオブジェクトを検索します。このメソッドは、Equalsメソッドを使用して同等性を判断します。

解決:

したがって、次のようにConverterを介してSelectedValueを使用してSelectedIndexを設定してください。

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

幸運を! :)

6
Pavel Kovalev

SelectedValuePathSelectedValueの型は完全に同じでなければなりません。

たとえば、SelectedValuePathのタイプがInt16およびSelectedValueにバインドするプロパティのタイプはintであり、機能しません。

私はそれを見つけるのに何時間も費やします、そしてそれは私が質問が尋ねられた多くの時間の後にここで答えている理由です。同じ問題を抱えている私のような別の貧しい人がそれを見ることができるかもしれません。

5
Dummy01

同様のことを実行し、最後にドロップダウンのSelectionChangedイベントにサブスクライブし、それでデータプロパティを設定しました。愚かで、それが必要ではなかったが、うまくいったことを願う。

3
Alden Snow

コンボボックスのxamlにSelectedValuePath = "Content"を設定し、SelectedValueをバインディングとして使用するのは妥当ですか?

文字列のリストがあり、コンボボックス内の実際のアイテムコンテンツに対して文字列のマッチングを行うようにバインドする必要があるようです。少なくとも、私がこの問題に出くわしたとき、それは私のために働いた。

ContentはSelectedValueの賢明なデフォルトのようですが、おそらくそうではないでしょうか?

2
Mikeb

SelectNameが更新されたことを通知するイベント、たとえばOnPropertyChanged( "SelectedName")を発生させましたか?それは私のために働いた。

1
davidinjc

私の場合、文字列にバインドする必要がありますが、リストにバインドしていました。

私がやっていたこと:

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
Rajon Tanducar

ご存知のように...私は今日この問題と何時間も戦い続けてきましたが、私が見つけたことを知っていますか?これはDataTypeの問題でした! ComboBoxに入力されたリストはInt64であり、Int32フィールドに値を保存しようとしていました!エラーはスローされず、値を保存していませんでした!

0
VBRocks

これを解決しました。えっ!!!どちらかを使用してください[...] .SelectedValue | .SelectedItem | .SelectedTextヒント:ComboStyle.DropDownListにはSelected Valueが推奨され、ComboStyle.DropDownには.SelectedTextが推奨されます。

-これで問題が解決するはずです。この小さなfynを解決するのに1週間以上かかりました。ハァッ!

0
Sam Darteh

ソースは更新する必要があるため、バインディングモードはOneWayToSourceまたはTwoWayである必要があります。モードOneWayはターゲットからソースへのソースであるため、ソースは読み取り専用になり、ソースは更新されません。

0
Chuck Borcher