Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Button mit ItemsSource
Sascha87
myCSharp.de - Member



Dabei seit:
Beiträge: 48

Themenstarter:

Button mit ItemsSource

beantworten | zitieren | melden

Guten Morgen zusammen,
ich möchte ein ItemsSource an ein Button Binden. Der Grund ist, ich benötige Unterwerte einer Klasse.

Bei einer ListBox kann ich "Rechte" als ItemsSource Binden und in den ListBox.ItemTemplates kann ich tiefer darauf zugreifen (Rechte.HatRechte).

Leider geht es bei den Buttons nicht. Dort kann ich nur "Rechte" Binden. Nach ein wenig googln kam ich auf die Funktion "ItemsControl".


<ItemsControl ItemsSource="{Binding Rechte}" >
                                            <ItemsControl.ItemTemplate>
                                                <DataTemplate>
                                                    <StackPanel>
                                                        <Button Content="Löschen" Command="{Binding FoerderLoeschen}" FontSize="{Binding SelectedFont, UpdateSourceTrigger=PropertyChanged}" Visibility="{Binding Rechte.CanDelFPFoer, Converter={StaticResource BoolToVis}}" Padding="5 5 5 5" Margin="5 15 5 0"/>
                                                    </StackPanel>
                                                </DataTemplate>
                                            </ItemsControl.ItemTemplate>
                                        </ItemsControl>

Soweit kann ich "Rechte" Binden und in dem Button auf "Rechte.CanDelFPFoer" zugreifen. Mein Problem ist, ich bekomme für jeden Unterwert einen Button ausgegeben. Sprich statt 1 Button bekomme ich in dem Fall 30. Wie kann ich das auf 1 Button begrenzen? Gibt es eine Alternative zu ItemsControl? Gehe ich die Sache komplett falsch an?

Vielen lieben Dank und Grüße
Sascha
private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


Dabei seit:
Beiträge: 1.811
Herkunft: Düsseldorf

beantworten | zitieren | melden

Wenn Du die Rechte nur als Liste hast, musst Du im ViewModel für eine Property mit einem Recht sorgen.
Danach schreibst Du als Binding einfach "{Binding MyRecht.WhatEver}".
private Nachricht | Beiträge des Benutzers
Sascha87
myCSharp.de - Member



Dabei seit:
Beiträge: 48

Themenstarter:

beantworten | zitieren | melden

Hättest du eventuell einen Tipp wie ich innerhalb einer Property nur auf ein Element der Klasse zugreife?

EDIT: Hat sich erledigt.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Sascha87 am .
private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


Dabei seit:
Beiträge: 1.811
Herkunft: Düsseldorf

beantworten | zitieren | melden

Du meinst "Array" oder "Liste" oder was auch immer Du da hast und nicht "Klasse", das ist was anderes.
Und ja, das geht, in einem WPF-Binding kann man auch auf ein einzelnes Item einer Auflistung zugreifen:
binding-in-wpf-to-element-of-array-specified-by-property
Ob das so gut ist, sei mal dahingestellt, ich habe in meiner ganzen Laufbahn noch keinen Fall gehabt, wo ich das gebraucht habe.
private Nachricht | Beiträge des Benutzers
Sascha87
myCSharp.de - Member



Dabei seit:
Beiträge: 48

Themenstarter:

beantworten | zitieren | melden

Ok, ich glaube, ich bin ein Schritt weiter.

Ich habe jetzt die folgende Property erstellt:


Recht _rechte;
        public Recht ProRechte
        {
            get
            {
                return _rechte;
            }
            set
            {
                if (value == null)
                    return;
                OnPropertyChanged(ref _rechte, value);
            }
        }

Im xaml Code kann ich auf den Wert zugreifen:


<Button Content="Löschen" Command="{Binding FoerderLoeschen}" FontSize="{Binding SelectedFont, UpdateSourceTrigger=PropertyChanged}" Visibility="{Binding ProRechte.CanDelFPFoer, Converter={StaticResource BoolToVis}}" Padding="5 5 5 5" Margin="5 15 5 0"/>

Nur gibt er mir keinen Wert aus?
Was ich vorhabe: Ich habe in der Datenbank eine 1 oder NULL gespeichert.
Ich lese die Werte als Nullable Bool aus und gebe sie als Liste weiter.

Ich möchte die Buttons anzeigen oder verstecken, je nach Wert. Dazu gibt es den BooleanToVisibilityConverter.

Allerdings wandelt er es nicht um bzw. ich vermute, dass ich meinen Wert nicht bekomme. Kann ich irgendwie überprüfen, ob true oder false ankommt?

Vielen lieben Dank!
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Sascha87 am .
private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


Dabei seit:
Beiträge: 1.811
Herkunft: Düsseldorf

beantworten | zitieren | melden

Zitat
Nur gibt er mir keinen Wert aus?
Ist die Property null?
Der musst Du natürlich auch ein Recht geben.
Zitat
Allerdings wandelt er es nicht um bzw. ich vermute, dass ich meinen Wert nicht bekomme. Kann ich irgendwie überprüfen, ob true oder false ankommt?
Du kannst einen Breakpoint im Converter setzen.
private Nachricht | Beiträge des Benutzers
Sascha87
myCSharp.de - Member



Dabei seit:
Beiträge: 48

Themenstarter:

beantworten | zitieren | melden

Im getter steht er anscheinend auf Null....
private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


Dabei seit:
Beiträge: 1.811
Herkunft: Düsseldorf

beantworten | zitieren | melden

Wie gesagt: Der musst Du natürlich auch ein Recht geben.
Wenn Du nichts zuweist, wird sie auch immer null zurück geben.
private Nachricht | Beiträge des Benutzers
Sascha87
myCSharp.de - Member



Dabei seit:
Beiträge: 48

Themenstarter:

beantworten | zitieren | melden

Das habe ich bisher noch nicht benötigt. Wie gebe ich dem denn Rechte?
private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


Dabei seit:
Beiträge: 1.811
Herkunft: Düsseldorf

beantworten | zitieren | melden

Das ist eine Property im ViewModel, die kannst Du zuweisen, wie jede andere Property auch.
Wenn Du sie aus der View heraus zuweisen willst, musst Du sie binden, viele Listen-Controls haben dafür eine SelectedItem-Property.
private Nachricht | Beiträge des Benutzers
Sascha87
myCSharp.de - Member



Dabei seit:
Beiträge: 48

Themenstarter:

beantworten | zitieren | melden

Das war der entscheidende Hinweis!

Vielen lieben Dank!

Grüße
Sascha
private Nachricht | Beiträge des Benutzers
Sascha87
myCSharp.de - Member



Dabei seit:
Beiträge: 48

Themenstarter:

beantworten | zitieren | melden

Das Anzeigen und Nicht-Anzeigen des Buttons habe ich hinbekommen.
Ich habe einfach eine Liste um den Button erstellt. Dort konnte ich ItemsSource und SelectedItem anwenden. Jetzt kann ich nur nicht mehr auf den Command des Buttons zugreifen.

Dem Binding habe ich ein "RelativeSource" hinzugefügt. Die eigentliche Bindung zum Command funktioniert. Allerdings führt er nichts aus.


<UserControl.DataContext>
        <vm:ViewModel></vm:ViewModel>
    </UserControl.DataContext>


<ListBox ItemsSource="{Binding Rechte, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding ProRechte, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" FontSize="{Binding SelectedFont, UpdateSourceTrigger=PropertyChanged}" BorderThickness="0" Background="WhiteSmoke">
                                        <ListBox.ItemContainerStyle>
                                            <Style TargetType="ListBoxItem">
                                                <Setter Property="Visibility" Value="{Binding CanAddFPFoer, Converter={StaticResource BoolToVis}}" />
                                            </Style>
                                        </ListBox.ItemContainerStyle>
                                        <ListBox.ItemTemplate>
                                            <DataTemplate>
                                                <StackPanel Orientation="Horizontal">
                                                    <Button Content="Eintragen" Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type vm:ViewModel}}, Path=FoerderEintragen}" Padding="5 5 5 5" Margin="5 15 5 0" />
                                                </StackPanel>
                                            </DataTemplate>
                                        </ListBox.ItemTemplate>
                                    </ListBox>


Als Bindungsfehler taucht folgendes aus:
Fehler
Quelle nicht gefunden: RelativeResource FindAncestor, AncestorType="ViewModel", AncestorLevel="1"

Hätte jemand einen heißen Tipp für mich?
Vielen lieben Dank und einen guten Start in den Tag!
Grüße
Sascha
private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


Dabei seit:
Beiträge: 1.811
Herkunft: Düsseldorf

beantworten | zitieren | melden

Warum machst Du das denn nicht im ViewModel?
Einfach die Liste mit den Rechten auf CanAddFPFoer filtern und einer zweiten Property zuweisen - oder direkt die erste Liste gefiltert anbieten.
Und wenn es immer nur ein Recht geben kann, suchst Du halt das eine Recht raus.
Dann brauchst Du den ganzen Kram nicht.

Fehler
Quelle nicht gefunden: RelativeResource FindAncestor, AncestorType="ViewModel", AncestorLevel="1"

AncestorType meint Controls - die RelativeSource sucht den LogicalTree ab. Das ViewModel hat damit nichts zu tun, das befindet sich im DataContext, der vom Binding als Default-Quelle verwendet wird.
Im ItemsControl bzw. dem ItemTemplate davon wird allerdings das tatsächliche Item als DataContext gesetzt, wenn Du an das ursprüngliche ViewModel kommen willst, suchst Du am besten mit der RelativeSource ein Control weiter oben (z.B. ListBox) und bindest darüber dann an DataContext.FoerderEintragen


Und ein paar andere Kommentare:
- Binding-Mode musst Du quasi nie setzen, meist passt der Default
- UpdateSourceTrigger brauchst Du nur, wenn die ViewModel-Property auch aktualisiert werden soll, z.B. SelectedFont - ich bezweifle, dass die ListBox die Source aktualisiert
- Im ItemTemplate ist genau ein Item drin, das StackPanel brauchst Du nicht
private Nachricht | Beiträge des Benutzers
Sascha87
myCSharp.de - Member



Dabei seit:
Beiträge: 48

Themenstarter:

beantworten | zitieren | melden

Zitat von Palladin007
Warum machst Du das denn nicht im ViewModel?
Einfach die Liste mit den Rechten auf CanAddFPFoer filtern und einer zweiten Property zuweisen - oder direkt die erste Liste gefiltert anbieten.
Und wenn es immer nur ein Recht geben kann, suchst Du halt das eine Recht raus.
Dann brauchst Du den ganzen Kram nicht.

Ich bin absoluter Anfänger und verstehe den Ansatz nicht. Daher versuche ich mit Lösungen zurecht zu kommen, die es im Internet gibt.

Deinen Tipp werde ich versuchen, vielen lieben Dank!
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Sascha87 am .
private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


Dabei seit:
Beiträge: 1.811
Herkunft: Düsseldorf

beantworten | zitieren | melden

Das, was Du im ViewModel machen musst, hat nichts mit WPF zu tun - außer das OnPropertyChanged, aber das hast Du ja schon.

Wenn Du noch Anfänger bist, ist WPF nicht der richtige Einstieg für dich.
Fang vorne an und lerne lieber erst mal die C#-Grundlagen und was OOP ist und was man damit macht.

Code-Snippets ohne Verständnis aus dem Internet zusammen zu kopieren hat sich noch nie bewehrt.
private Nachricht | Beiträge des Benutzers