Laden...

WPF Listbox SelectedItem Wert aus Teplate

Letzter Beitrag vor 2 Jahren 13 Posts 721 Views
WPF Listbox SelectedItem Wert aus Teplate

Hallo

Ich habe eine Listbox mit einem ItemTemplate. Dieses Template implementiert mehrere StackPanel mit Textblöcken , die an eine ObservableCollection im VM gebunden sind.
Nun würde ich gern lediglich einen Wert (ID) des gewählten Item zurück geben und nicht das ganze Item. Wie lässt sich das im XAML lösen? (Ein Model des Item hab ich angehängt)

Hallo MMCSharp

So ganz verstanden habe ich das nicht, wie es bei dir aussieht. Ohne Code kann man da nur raten.

Prinzipiell würde ich sagen, dass du dafür einen IValueConverter verwendest: Wertumwandlung mit IValueConverter - The complete WPF tutorial

Gruß
Alf

Ich würde gern einfach nur den Wert der ID des SelectedItem im VM binden und nicht das ganze Item. Aktuell bekomme ich das Item (das einem Model entspricht) nach der Selektierung.

Prinzipiell ist das auch die Idee, dass Du natürlich das "ganze" Item bekommst, weil das auch die Quelle darstellt.
Aber die ListBox unterstützt für gewisse Sachen auch mehr: How to: Use SelectedValue, SelectedValuePath, and SelectedItem - WPF .NET Framework (hier Sample TreeView, das Prinzip ist identisch).

PS: mit dem Bild kann wahrscheinlich fast niemand was anfangen. Auch ich hab keine Ahnung, was das darstellen soll.
Poste doch einfach ein Code Snippet?

Hier der XAML- Codeausschnitt


                    <ListBox x:Name="ListLocations"
                            AlternationCount="2"
                            Background="#FF1F1F1F"
                            ItemContainerStyle="{DynamicResource _ListBoxItemStyle}"
                            SelectedItem="{Binding ID, Mode=twoWay}"
                            ItemsSource="{Binding WareHouseCollection}"
                            SelectedValuePath="@Id"
                            Margin="0,5,0,0"
                            Grid.Row="1" 
                            IsSynchronizedWithCurrentItem="True">
                       
                       
                        
                        <ListBox.ItemTemplate>
                            <DataTemplate x:Name="WareHouseTamplet">
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="Auto"/>
                                        <ColumnDefinition Width="Auto"/>
                                    </Grid.ColumnDefinitions>

                                    <!--#region Left Item area-->
                                    <Grid>

                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="50"/>
                                        </Grid.ColumnDefinitions>

                                        <Grid Grid.Column="0">
                                            <Grid.RowDefinitions>
                                                <RowDefinition Height="Auto"/>
                                                <RowDefinition Height="Auto"/>
                                            </Grid.RowDefinitions>

                                            <TextBlock Grid.Row="0" Name="LblID" 
                                                       Margin="5,0,0,0" FontSize="16" 
                                                       HorizontalAlignment="Left" Foreground="White" FontWeight="Bold" Text="{Binding Id}" />

                                            <svgc:SvgViewbox Width="25" Grid.Row="1" 
                                                             HorizontalAlignment="Left" VerticalAlignment="Center" 
                                                             Height="35" Source="Assets/Icons/right-arrow.svg" />

                                        </Grid>

                                    </Grid>

                                    <!--#endregion-->

                                    <!--#region Right Item area-->
                                    <Grid Grid.Column="1">
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="Auto"/>
                                            <RowDefinition Height="Auto"/>
                                            <RowDefinition Height="Auto"/>
                                        </Grid.RowDefinitions>

                                        <StackPanel Orientation="Horizontal" Grid.Row="0" Height="Auto">
                                            <TextBlock Name="LbLStockName" Margin="4,2,0,0" FontWeight="Bold" Foreground="White" Text="{Binding StockName}" Height="20"/>
                                        </StackPanel>

                                        <StackPanel Orientation="Horizontal" Grid.Row="1" Margin="0,3,0,0" Height="Auto">
                                            <TextBlock Name="LblStreet" Margin="5,0,0,0" Foreground="White" Text="{Binding Street}" Height="20"/>
                                            <TextBlock Name="LbLHousenumber" Margin="4,0,0,0" Foreground="White" Text="{Binding HouseNumber}" Height="20"/>
                                        </StackPanel>

                                        <StackPanel Orientation="Horizontal" Grid.Row="2" Height="Auto">
                                            <TextBlock Name="LblPostcode" Margin="5,0,0,2" Foreground="White" Text="{Binding Postcode}" />
                                            <TextBlock Name="LbLCity" Margin="4,0,0,2" Foreground="White" Text="{Binding City}" />
                                        </StackPanel>
                                    </Grid>
                                    <!--#endregion-->

                                </Grid>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>

und die Property im VM sieht momentan so aus


       private LocationModel? selectedItem;
       public LocationModel? SelectedItem
       {
            get { return selectedItem; }
            set
            {
                selectedItem = value;
                ID = value.Id;
                RaisePropertyChanged();
            }
       }

Nun würde ich aber gern einfach nur die Id als Property abgreifen:


   private int  id;
   public int ID
   {
            get { return id; }
            set 
            { 
                id = value;
                RaisePropertyChanged();
            }
     }

Das ergibt so aber keinen Sinn mit der Eigenschaft Id (so hättest du ja für die gesamte ListBox nur eine Id).

Willst du vllt. einfach so etwas?


public int SelectedID
{
    get { return SelectedItem?.Id; }
}

(ID = value.Id im Setter von SelectedItem ist dann überflüssig)

Wobei man so oder so dann auch nen Property Changed für die Id werfen sollte..
Sonst bekommt ja nie jemand was mit, wenn man nur auf die Id hört.

Ich würde einfach nur gern aus dem ausgewählten Item die Id abgreifen und mit dieser dann weiter arbeiten, ohne das ganze Model im VM abzufangen. Es geht wohl auch so, aber mir gefällt die LocationModel Property nicht im VM. Deshalb würde ich gerne nur die ID Binden. Das würde ich gern schon im XAML so Biden, dass direkt die Id aus dem Item übergeben wird. Oder ist dieses Handling falsch?

Was klappt denn an der Erklärung nicht, die ich Dir weiter oben gegeben hab?
How to: Use SelectedValue, SelectedValuePath, and SelectedItem - WPF .NET Framework

Entschuldigung @Abt .... Deine Lösung klappt und ist das was ich gesucht habe! Vielen Dank!

Jetzt hab ich noch ein Problem. Die ListBox zeigt einen Fehler, wenn nichts selectirt ist. Der Rahmen wird dann rot. Lässt sich das unterdrücken?

Dann hast du einen Binding-Fehler, s.a. Mysterious red border appears around ComboBox (gilt für alle Listenelemente).

Wenn du int-Werte (also Wertetypen) bindest, dann muß ja immer ein Wert zugewiesen sein (und wenn es 0 ist), ansonsten auf int? (also Nullable<int>) binden.

Super! Das hat geklappt! Dankeschön!