none
ComboBox Datenbindung innerhalb einer ListView RRS feed

  • Frage

  • Guten Tag

    In einer ListView, welche die Daten per Bindung von einer Klasse erhält, habe ich einen TextBlock, einen ToggleSwitch und eine ComboBox. Die Bindung an den TextBlock und den ToggleSwitch funktioniert einwandfrei (TwoWay Binding). Leider klappt das Binding für die ComboBox nicht. Die Elemente habe ich mithilfe von ComboBoxItem direkt in XAML definiert, die Bindung, welches Item angewählt ist, soll daher auch im TwoWay Mode stattfinden. Wie bewerkstellige ich das genau?

    Mit freundlichen Grüssen

    Freitag, 7. August 2015 09:15

Antworten

  • Hallo Andy,

    in XAML ist es so das das ausgewählte Element immer dem entspricht was auch angezeigt wird. Das heißt das eine ComboBox mit ComboBoxItems aus wirklich entsprechende Items in SelectedItem zurück gibt. Eine per Datenbindung gefüllte ComboBox dagegen kann auch Strings ausgewählt haben, sofern die übergebene Liste welche enthält.

    Daher musst du entweder SelectedIndex binden und darüber bestimmen was ausgewählt wurde oder aber du befüllst die ComboBox doch wieder per ItemsSource und kannst direkt das ausgewählte Item binden.


    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    • Als Antwort markiert andy-dev Samstag, 8. August 2015 18:18
    Freitag, 7. August 2015 12:09
  • Hi,
    das funktioniert schon richtig. Du musst aber berücksichtigen, dass Du im Falle von ComboBoxItems im XAML mit gebundenen SelectedIndex arbeiten solltest. Wenn Du mit SelectedItem arbeiten willst, dann muss die gebundene Eigenschaft vom Typ ComboBoxItem sein. In diesem Fall hast Du dann etwas mehr Aufwand für eine Konvertierung. Besser ist es deshalb mit einer Liste vom Ojekten zu arbeiten, die als ItemsSource an die Combobox gebunden werden.

    Hier mal meine Demo:

    XAML:

          <ListView DataContext="{Binding Source={StaticResource vm}}" ItemsSource="{Binding View}">
            <ListView.ItemTemplate>
              <DataTemplate>
                <Border BorderBrush="Red" BorderThickness="2">
                  <Grid>
                    <Grid.RowDefinitions>
                      <RowDefinition/>
                      <RowDefinition/>
                      <RowDefinition/>
                      <RowDefinition/>
                    </Grid.RowDefinitions>
                    <TextBlock Grid.Row="0" Text="{Binding AnzeigeText}" />
                    <ToggleSwitch Grid.Row="1" IsOn="{Binding Toggle}" />
                    <ComboBox Grid.Row="2" SelectedItem="{Binding CbItem, Mode=TwoWay}">
                      <ComboBox.Items>
                        <ComboBoxItem Content="Item1"/>
                        <ComboBoxItem Content="Item2"/>
                        <ComboBoxItem Content="Item3"/>
                      </ComboBox.Items>
                    </ComboBox>
                    <TextBox Grid.Row="3" Text="{Binding CbItemIndex, Mode=TwoWay}"/>
                  </Grid>
                </Border>
              </DataTemplate>
            </ListView.ItemTemplate>
          </ListView>

    Dazu der ViewModel:

    Public Class Page02VM
    
      Private liste As ObservableCollection(Of Page02Data)
      Private cvs As CollectionViewSource
    
      Public ReadOnly Property View As ICollectionView
        Get
          If liste Is Nothing Then
            liste = New ObservableCollection(Of Page02Data)
            DatenLaden(liste)
            cvs = New CollectionViewSource() With {.Source = liste}
          End If
          Return cvs.View
        End Get
      End Property
    
      Private Sub DatenLaden(liste As ObservableCollection(Of Page02Data))
        Dim rnd As New Random
        For i = 1 To 10
          liste.Add(New Page02Data With {
                    .AnzeigeText = String.Format("Zeile 1 {0}Text {1}", vbNewLine, i),
                    .Toggle = rnd.NextDouble > 0.5,
                    .CbItemIndex = rnd.Next(3)})
        Next
      End Sub
    
    End Class
    
    Public Class Page02Data
      Implements INotifyPropertyChanged
      Public Property AnzeigeText As String
      Public Property Toggle As Boolean
    
      Private _cbItemIndex As Integer
      Public Property CbItemIndex As Integer
        Get
          Return Me._cbItemIndex
        End Get
        Set(value As Integer)
          If Me._cbItemIndex <> value Then
            Me._cbItemIndex = value
            OnPropertyChanged()
          End If
        End Set
      End Property
    
      Private _cbItem As ComboBoxItem
      Public Property CbItem As ComboBoxItem
        Get
          Return Me._cbItem
        End Get
        Set(value As ComboBoxItem)
          Me._cbItem = value
        End Set
      End Property
    
    #Region " OnPropertyChanged"
    
      Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
      Private Sub OnPropertyChanged(<CallerMemberName> Optional propName As String = "")
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propName))
      End Sub
    
    #End Region
    
    End Class
    


    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks

    • Als Antwort markiert andy-dev Samstag, 8. August 2015 18:18
    Samstag, 8. August 2015 13:46
  • Hi,
    wie Tom Dir schon geraten hat, kann ich Dir auch nur raten, auf ComboBoxItems im XAML zu verzichten und eine Liste mit Objekten zu binden. Dann bekommst Du als SelectedItem das gewünschte ausgewählte Objekt und kannst ohne großen Aufwand auf die Innereien zugreifen.

    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks

    • Als Antwort markiert andy-dev Samstag, 8. August 2015 20:29
    Samstag, 8. August 2015 20:18

Alle Antworten

  • Hallo Andy,

    in XAML ist es so das das ausgewählte Element immer dem entspricht was auch angezeigt wird. Das heißt das eine ComboBox mit ComboBoxItems aus wirklich entsprechende Items in SelectedItem zurück gibt. Eine per Datenbindung gefüllte ComboBox dagegen kann auch Strings ausgewählt haben, sofern die übergebene Liste welche enthält.

    Daher musst du entweder SelectedIndex binden und darüber bestimmen was ausgewählt wurde oder aber du befüllst die ComboBox doch wieder per ItemsSource und kannst direkt das ausgewählte Item binden.


    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    • Als Antwort markiert andy-dev Samstag, 8. August 2015 18:18
    Freitag, 7. August 2015 12:09
  • Vielen Dank für die schnelle Antwort. Leider muss ich in die jeweilige Comboboxen der ListView immer die selben Items zur Auswahl haben, deshalb habe ich diese per XAML als ComboBoxItems fix definiert. Das ausgewählte Item des jeweiligen ListViewItem muss ich allerdings binden können, leider will das überhaupt nicht funktionieren. Ev habe ich deine Antwort aber auch nicht ganz richtig verstanden.

    Mit freundlichen Grüssen

    Freitag, 7. August 2015 15:18
  • Wo ist das Problem? Die ComboBox kannst du trotzdem per Datenbindung befüllen sofern du eine entsprechende Liste ins ViewModel/DataContext packst.

    Sonst gilt weiterhin das du entweder das ComboBoxItem, das Datengebundene Element einer Datengebundenen ComboBox oder aber den Index auslesen kannst.


    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Freitag, 7. August 2015 15:43
  • Hi,
    das funktioniert schon richtig. Du musst aber berücksichtigen, dass Du im Falle von ComboBoxItems im XAML mit gebundenen SelectedIndex arbeiten solltest. Wenn Du mit SelectedItem arbeiten willst, dann muss die gebundene Eigenschaft vom Typ ComboBoxItem sein. In diesem Fall hast Du dann etwas mehr Aufwand für eine Konvertierung. Besser ist es deshalb mit einer Liste vom Ojekten zu arbeiten, die als ItemsSource an die Combobox gebunden werden.

    Hier mal meine Demo:

    XAML:

          <ListView DataContext="{Binding Source={StaticResource vm}}" ItemsSource="{Binding View}">
            <ListView.ItemTemplate>
              <DataTemplate>
                <Border BorderBrush="Red" BorderThickness="2">
                  <Grid>
                    <Grid.RowDefinitions>
                      <RowDefinition/>
                      <RowDefinition/>
                      <RowDefinition/>
                      <RowDefinition/>
                    </Grid.RowDefinitions>
                    <TextBlock Grid.Row="0" Text="{Binding AnzeigeText}" />
                    <ToggleSwitch Grid.Row="1" IsOn="{Binding Toggle}" />
                    <ComboBox Grid.Row="2" SelectedItem="{Binding CbItem, Mode=TwoWay}">
                      <ComboBox.Items>
                        <ComboBoxItem Content="Item1"/>
                        <ComboBoxItem Content="Item2"/>
                        <ComboBoxItem Content="Item3"/>
                      </ComboBox.Items>
                    </ComboBox>
                    <TextBox Grid.Row="3" Text="{Binding CbItemIndex, Mode=TwoWay}"/>
                  </Grid>
                </Border>
              </DataTemplate>
            </ListView.ItemTemplate>
          </ListView>

    Dazu der ViewModel:

    Public Class Page02VM
    
      Private liste As ObservableCollection(Of Page02Data)
      Private cvs As CollectionViewSource
    
      Public ReadOnly Property View As ICollectionView
        Get
          If liste Is Nothing Then
            liste = New ObservableCollection(Of Page02Data)
            DatenLaden(liste)
            cvs = New CollectionViewSource() With {.Source = liste}
          End If
          Return cvs.View
        End Get
      End Property
    
      Private Sub DatenLaden(liste As ObservableCollection(Of Page02Data))
        Dim rnd As New Random
        For i = 1 To 10
          liste.Add(New Page02Data With {
                    .AnzeigeText = String.Format("Zeile 1 {0}Text {1}", vbNewLine, i),
                    .Toggle = rnd.NextDouble > 0.5,
                    .CbItemIndex = rnd.Next(3)})
        Next
      End Sub
    
    End Class
    
    Public Class Page02Data
      Implements INotifyPropertyChanged
      Public Property AnzeigeText As String
      Public Property Toggle As Boolean
    
      Private _cbItemIndex As Integer
      Public Property CbItemIndex As Integer
        Get
          Return Me._cbItemIndex
        End Get
        Set(value As Integer)
          If Me._cbItemIndex <> value Then
            Me._cbItemIndex = value
            OnPropertyChanged()
          End If
        End Set
      End Property
    
      Private _cbItem As ComboBoxItem
      Public Property CbItem As ComboBoxItem
        Get
          Return Me._cbItem
        End Get
        Set(value As ComboBoxItem)
          Me._cbItem = value
        End Set
      End Property
    
    #Region " OnPropertyChanged"
    
      Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
      Private Sub OnPropertyChanged(<CallerMemberName> Optional propName As String = "")
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propName))
      End Sub
    
    #End Region
    
    End Class
    


    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks

    • Als Antwort markiert andy-dev Samstag, 8. August 2015 18:18
    Samstag, 8. August 2015 13:46
  • Vielen Dank für die Hilfe hat nun Problemlos geklappt. Das Problem lag daran, dass ich erst nicht ganz verstanden habe, was es mit SelectedIndex auf sich hat, bzw. bis ich dann gemerkt habe, dass eben jeweils dieser zurückgegeben wird, wenn man die ComboBoxItems in XAML definiert. Nun habe ich die Datenbindung an SelectedIndex und prüfe jeweils, um welches Item es sich handelt. Vielen Dank!

    Mit freundlichen Grüssen

    Samstag, 8. August 2015 18:21
  • Hi,
    wie Tom Dir schon geraten hat, kann ich Dir auch nur raten, auf ComboBoxItems im XAML zu verzichten und eine Liste mit Objekten zu binden. Dann bekommst Du als SelectedItem das gewünschte ausgewählte Objekt und kannst ohne großen Aufwand auf die Innereien zugreifen.

    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks

    • Als Antwort markiert andy-dev Samstag, 8. August 2015 20:29
    Samstag, 8. August 2015 20:18