Guten Tag,
zum einem muss ich sagen, dass ich noch relativ neu in der WPF-Welt bin und im Moment versuche anhand eines Projekts was ich realisieren will das ganze Thema zu verstehen. Ich denke, ich bin auch schon ziemlich weit gekommen, an einer Stelle hänge ich jedoch jetzt fest.
Was will ich machen?
Ich hab ein Window mit einem Menü Links auf der Seite (z. B. Artikelliste, Neuer Artikel usw.). Wenn ich auf einen dieser Button klicke, öffnet sich ein neuer Tab. Im Tab ist ein "X" Button zum schließen des Tabs. Das war erstmal grob
Was funktioniert schon? Was hab ich schon gemacht?
Ich hab eine Klasse "Workspaces". Diese Klasse beinhaltet eine ObservableCollection Namens "Container". Die Items der Klasse sind vom Typ "TabBase". Die Klasse TabBase ist quasi der gemeinsame Nenner für alle Tabarten (z. B. Klasse TabArtikelliste und TabNeuerArtikel). Wenn ich den Container nun über einen Button im Menü befülle, wird der Tab automatisch im Control angezeigt. Anhand von ItemSource, DataTemplates und Content- ItemSource-Selectoren wird das richtige Design ausgewählt usw. Soweit funktioniert das auch schon ganz gut.
Was ist mein Problem?
Wenn ich auf den Button "X" im Tab klicke, bin ich bereits in einer Methode "Remove", die ich durch einen Command aufrufe. Dem Command übergebe ich den "Sender" als Objekt. Und hier kommt mein Problem: Ich muss jetzt das richtige Item aus der ObservableCollection löschen und finde beim besten Willen nicht raus, wie ich an das richtige Item komme. Ich habe den Sender, der Sender ist allerdings vom Typ "TabItem", in meiner Observ-Collection sind aber Items vom Typ "TabBase". Wie bitte komme ich jetzt an das Item was ich aus der Collection löschen muss? Probiere das jetzt schon seit 2 Wochen und gebe langsam auf 🙁
Interessant ist, dass wenn ich mir die "Sender"-Variable anschaue, dort folgendes steht {System.Windows.Controls.TabItem Header:<Namespace>.ArtikelList Content:<Namespace>.ArtikelList}. Heißt: Anscheinend ist dem Item zumindestens schon bekannt von welchem Typ es ist -> ArtikelList.
Ich hoffe ich konnte mein Problem halbwegs vernünftig schildern und ihr könnt mir helfen! Zur Not könnte ich auch heute Abend noch ein paar Code-Schnippsel hier rein kopieren, falls es hilft.
Hi Jacyrio,
du kannst dem Command per CommandParameter die Id des zu löschenden ViewModels mitgeben. Dann kann das Command den richtigen Eintrag aus der ObservableCollection löschen. Wenn du das MVVM-Pattern verwendest, dann sollte dein TabControl automatisch aktualisiert weren.
Christian
Weeks of programming can save you hours of planning
Das würde mir definitiv weiter helfen. Kannst du mir auch noch auf die schnelle sagen was ich als Parameter übergeben muss damit ich die ID erhalte? Ansonsten suche ich danach.
Und: Ich vermute mal es gibt keine Möglichkeit von dem Sender-Item zu dem TabBase-Item zu kommen, oder? Hätte mich auch gefragt wie das funktionieren soll...
Hallo Jacyrio,
das kannst du übers xaml machen, da wo du das Command bindest "CommandParameter=..." oder du lässt das Command das VM kennen und rufst es von dort ab.
Gruss
Coffeebean
Microsoft MVP // Me // Blog // GitHub // @Egghead // All my talks // Speakerdeck
Hallo Coffeebean,
das war mir schon bekannt das ich das im CommandParameter übergeben muss. Ich weiß nur noch nicht was ich im CommandParamter="..." stehen muss, damit er die ID übergibt. Die Variante mit XAML würde mir am besten gefallen, die andere Möglichkeit mit dem VM würde mich allerdings auch interessieren (um einfach zu wissen was du meinst).
Ich bin, wie gesagt, noch relativ neu in dem Thema und muss noch ein bisschen was lernen.. mir fehlt dann noch das Wissen das ich nun selbst kombinieren könnte was genau du mit "Lässt das Command das VM kennen" meinst.. bzw. kann ich mir das schon vorstellen, an der Umsetzung würde es jetzt allerdings scheitern 😃
Irgendwoher muß doch das Command wissen, welchen Tab du schließen willst. Also mußt du (irgendeinen) eindeutigen Bezeichner mitgeben. Das kann eine ID sein, die du selbst vergeben hast, oder einfach der Index des Tabs.
Ich würde dir übrigens empfehlen, mal ein paar MVVM-Tutorials anzuschauen, damit du einen Überblick bekommst, wie das ganze funktioniert, und worauf man achten muß.
Christian
Weeks of programming can save you hours of planning
Ich tue seit 4 Wochen nix anderes als lesen..
Im Internet sowie ein Buch mit 1200 Seiten was ich mir nun gekauft hab..
Dauert halt ein wenig bis man das alles versteht.. und nur durchs lesen komm ich halt nicht immer an mein Ziel.. Namen vergeben kann ich schon machen.. ich dachte aber es gibt eine bessere Alternative und will halt die beste Alternative verwenden und nicht irgendetwas selbst zusammen gebautes..
Hallo Jacyrio,
bleiben wir mal beim Thema 😉
irgendeinen Identifier brauchst du ja. Wie schon mehrfach gesagt.
Das Tabcontrol hat ein Property "SelectedItem". Das kannst du auf dem Viewmodel binden oder du gibst es direkt per Parameter in das Command.
Dann hast du eine Collection von Tabs, die als ItemSource herhalten. Dies sollte eine Liste oder sowas sein und da schmeisst du dann eben das selektierte (SelectedItem. Ob nun per VM in das Command oder per CommandParameter ist, zumindest vorerst, irrelevant) raus.
Gruss
Coffeebean
Microsoft MVP // Me // Blog // GitHub // @Egghead // All my talks // Speakerdeck
Mach es doch einfach wie im MVVM Tutorial von Josh Smith und lass deine "Workspaces"-VMs ein RequestClose Event feuern im CloseCommand. Dieses abonierst du wenn ein Item deiner Collection hinzugefügt wird und im Eventhandler entfernst du es (siehe Tut).
Danke Lennart, werde ich mir anschauen 😃
@Coffeebean: Das mit dem SelectedItem hat bereits funktioniert. Allerdings habe ich das Problem, dass der Benutzer auch den Button drücken darf, wenn das Item nicht selektiert ist. Habe da aber auch schon eine Idee, die ich heut Abend mal ausprobieren werde.
Vielleicht löst sich das aber ja auch durch Lennarts Tutorial. Das Tut hatte ich schon mal offen, aber hab ich mit diesem Problem hier nicht in Verbindung gebracht.
Hallo nochmal,
hätte da nochmal 1-2 Fragen. Vorab: Bitte nicht wundern. Ich habe das Problem zwar auf eine andere Art und Weise gelöst, da ich aber mit einem Buch zusammen arbeite, probiere ich ständig wieder neue Arten aus wie ich evtl. auch anders an die Lösung komme.
@Lennart: Das Tutorial, was du mir gegeben hast, bin ich noch am durcharbeiten. Ich denke, dass werde ich aber wohl erst richtig verstanden haben, wenn ich das 1.200 Seiten Buch komplett durchgelesen habe 😦
@Alle:
Ich befinde mich, wie in diesem Thema bereits erwähnt, wieder in meiner "Remove"-Methode. Wenn ich den SelectedTabIndex mit an die Remove-Funktion übergebe, kann ich das Tab aus dem TabControl löschen. Jetzt möchte ich aber zwei andere Alternativen ausprobieren. Beide zielen darauf ab, dass ich das Tab nicht selektiert habe, wenn ich den Button klicke:
FrameworkElement el = sender as FrameworkElement;
TabControl tab = (TabControl)el.FindName("tabMain");
Würde ich das Tab finden, könnte ich anhand der "sender"-Variable das TabItem aus dem TabControl löschen. Problem ist, wenn ich die Funktion "FindName" ausführe, ist die Variable "tab" immer "NULL".
Ich vermute, dass liegt daran, dass ich die TabItems über ein DataTemplate generiere und für jedes DataTemplate (so wie ich es verstanden habe) ein neues NameScope-Objekt erstellt wird, heißt wiederum das NameScope-Objekt des TabItems kennt mein TabControl nicht und gibt deswegen NULL zurück! Stimmt das?! Übertrage ich testweise das Window an die Funktion und suche dann nach tabMain, finde ich mein Element!!
Dann aber die Frage: Wie komme ich von dem TabItem-Objekt per FindName an mein TabControl-Element? Etwas weiter hinten im Buch habe ich gelesen, dass es bei Templates auch die möglichkeit gibt mit "objekt.Template.Findname" zu arbeiten. Habe aber noch nicht rausgefunden wie das funktioniert und welches "templatesParent" ich übergeben könnte, damit ich mein TabControl finde.
Gibt es hierzu Lösungen?
Vielen Dank schonmal für die Antworten!
P.S. Ich kann mir vorstellen, dass für erfahrene WPF-Programmierer diese Fragen etwas "blöd" rüberkommen. Ich hoffe aber ihr versteht, dass ich im Moment noch am lernen bin und die Fragen hoffentlich irgendwann "professioneller" werden 😄
Hi Jacyrio,
Gibt es hierzu Lösungen?
Ja, und die wurde auch schon mehrmals genannt: MVVM und Datenbindung.
Hast du eine ObservableCollection an dein TabControl gebunden, brauchst du nur den passenden Eintrag aus der Collection zu löschen, um das TabControl zu aktualisieren. Im Code durch die Steuerelemente der View durchzugehen und diese zu manipulieren, ist eigentlich immer der falsche Ansatz.
Christian
Weeks of programming can save you hours of planning
Ich hab irgendwie das Gefühl, dass ich der einzige hier im Forum bin der irgendwann mal angefangen hat sich was beizubringen X( dann scheine ich hier wohl falsch zu sein...
Ich habe bereits vor meinem Post verstanden, dass ich das mit MVVM und Datenbindung machen kann. Ansonsten hätte ich nicht am Anfang gesagt, dass ich im Moment bin mir das beizubringen.
Das Problem ist im Moment in diesem Bereich nur das "Wie"..
Ja.. ich hab eine ObservableCollection an das TabControl gebunden und ja ich weiß auch wie mit dem Datenbindung-System ein Command aufrufe und den sender an das Command übergebe.. ich weiß aber immernoch nicht, wie ich dann von dem TabItem (was ich per Bindung an das Command übergebe) zu dem Objekt der ObservableCollection komme oder wie ich das Objekt der Collection an das Command übergebe..
Ihr habt mir zwar allgemeine Antworten gegeben, aber ohne konkrete Beispiele ist das halt als Neuling nicht grad einfach das zu verstehen.. In der Theorie verstehe ich das meiste, aber die praktische Erfahrung fehlt mir im Moment halt noch.
Aber ich werde das Beispiel von Lennart durcharbeiten und versuchen den kompletten Code zu verstehen und mich wieder melden, wenn ich sowieso schon das meiste kann.. ist anscheinend eher die Zielgruppe dieses Forums 🙂
MfG Jac
Ihr habt mir zwar allgemeine Antworten gegeben, aber ohne konkrete Beispiele ist das halt als Neuling nicht grad einfach das zu verstehen..
[Hinweis] Wie poste ich richtig? Punkt 4. Zumidnest in der Tendenz. Wir können dir gerne helfen und dir Stichworte nennen, was und wie du das löst, musst du konkret selber rausfinden, damit du...
In der Theorie verstehe ich das meiste, aber die praktische Erfahrung fehlt mir im Moment halt noch.
...eben genau die Erfahrung sammelst, damit du diese und ähnliche Probleme in Zukunft selber lösen kannst. Genau das ist einer der Zwecke dieses Forums 😉
Gruss
Coffeebean
PS: Jetzt bitte keine Diskussion ob das gut oder schlecht ist. Das wurde bisher unzählige Male besprochen.
Microsoft MVP // Me // Blog // GitHub // @Egghead // All my talks // Speakerdeck
Ich weiß nicht genau ob ich das Problem richtig verstanden habe da ich auch selber noch totaler WPF Neuling bin (und wahrscheinlich bald vor einem ähnlichen Fall stehe wie du jetzt), aber du schreibst doch ganz oben, dass der Sender so aussieht:
System.Windows.Controls.TabItem Header:<Namespace>.ArtikelList Content:<Namespace>.ArtikelList
Also diese "ArtikelList" klingt doch schon wie das Objekt das du suchst oder? Dann müsstest du doch über senderTabItem.Content das Objekt haben und dieses müsstest du dann aus der ObservableCollection löschen (?).
gruß
sth_Weird
Linux is for free...if your time is worth nothing
Fluchen ist die einzige Sprache, die jeder Programmierer perfekt beherrscht
++++++++++++++++++++~+