Benutzersteuerelement unsichtbar machen per Code

  • WPF

Es gibt 62 Antworten in diesem Thema. Der letzte Beitrag () ist von PadreSperanza.

    Benutzersteuerelement unsichtbar machen per Code

    Guten Morgen,

    ich habe eine Navigationsleiste mit Borders. Wenn man eines davon anklickt, sollen die UserCntrols im Hauptteil des Fensters dementsprechend per Code sichtbar/unsichtbar gemacht werden. Sozusagen als Registerkarte.

    Wenn ich nun in der Navigationsleiste.xaml.vb das hier eingebe:

    View.Suche.

    ist noch alles klar.

    Das UserControls ist in dem Fall Suche in meiner View.

    Wenn ich dann aber View.Suche.Visibility = Visibility.Hidden mache erscheint die Property nicht im Intellisense. Es funktioniert auch nicht über das Grid grdSuchen, das sich direkt im UserContol befindet, dieses wird ebenfalls nicht von IntelliSense angezeigt...

    Was mache ich falsch?

    kafffee schrieb:

    ich habe eine Navigationsleiste mit Borders. Wenn man eines davon anklickt, sollen die UserCntrols im Hauptteil des Fensters dementsprechend per Code sichtbar/unsichtbar gemacht werden. Sozusagen als Registerkarte.
    habich andernorts schon gesagt - das ist eine mir unbekannte Vorgehensweise - ich vermute, sie ist sehr nachteilhaft, aber probiert habichs so zugegebenermassen noch nie.

    Ich täte anderes empfehlen, insbesondere auch, die Denke umzustellen:
    "ich habe eine Navigationsleiste mit Borders."
    Nein - besser so:
    Ich habe eine Liste von anzuzeigenden Dingen im Viewmodel. Angezeigt werden sie in einer Listbox, unter Verwendung eines Datatemplates.
    Das Datatemplate hat eine Border.
    Die Listbox gestaltet auf diese Weise, was der User als "Navigationsleiste" wahrnehmen wird.

    "Wenn man eines davon anklickt, sollen die UserCntrols im Hauptteil des Fensters dementsprechend per Code sichtbar/unsichtbar gemacht werden."
    Nein - besser so:
    Ich habe eine Liste von anzuzeigenden Dingen im Viewmodel, gebunden an obige Listbox, welche das SelectedItem bestimmt.
    Ich habe einen ContentPresenter, gebunden an das SelectedItem.
    (U.U. sogar verschiedene) DataTemplates sorgen dafür, das das "Selected-Viewmodel" auf dem ContentPresenter ansprechend presented wird.

    Wie gesagt: das ist ein Detail-View:
    Links die Liste der Dinge, jeweils nur ganz knapp und platzsparend angezeigt.
    Rechts das links ausgewählte Ding, ausführlich präsentiert.
    Also zwei Controls werden auf verschiedene Weise an dieselbe ListCollectionView im Viewmodel gebunden.
    Das eine (ein Multi-Item-Control) präsentiert die ListCollectionView übersichtsweise, und zum Auswählen.
    Das andere präsentiert das ausgewählte ausführlich.
    @ErfinderDesRades

    Also das klingt doch ganz vernünftig, aber da brauche ich glaube jede Menge Hilfe...

    Fängt schon bei der ersten Zeile Code an, die ich geschrieben habe:

    Public Registerkarten() As UserControl = {View.Suche, View.PlattendecksView, View.EqualizerView, View.SettingsView}

    Die einzelnen Elemente werden zwar von IntelliSense vorgeschlagen, aber werden dann letztendendes rot unterstrichen mit dem Hinweis: "Suche"/"PlattendecksView"/etc. ist ein Klassentyp und kann nicht als Ausdruck verwendet werden...

    Anbei mal ein Bild, wie das dann letztenendes aussehen soll.

    Edit: Hab grad mal dein Tut "Vier Views" den Abschnitt des Detailviews mir reingehauen. Das hab ich soweit verstanden, ist aber weniger komplex wie jetzt meine Aufgabenstellung. Ich habe nämlich vier Views, jeweils als UserControl: SucheView.xaml, PlattendecksView.xaml, Equalizer View. xaml und SettingsView.xaml. Die will ich rechts anzeigen. Dann hab ich vier Icons, die will ich links anzeigen. Wie du das jetzt beides in dasselbe CollectionView reinpacken willst versteh ich jetzt noch nicht...
    Bilder
    • screenshot navigationsleiste.jpg

      144,77 kB, 2.560×1.080, 57 mal angesehen

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „kafffee“ ()

    kafffee schrieb:

    Public Registerkarten() As UserControl = {View.Suche, View.PlattendecksView, View.EqualizerView, View.SettingsView}
    Falsch.
    Im Code dürfen nur ViewModelse auftauchen, keine Views.

    kafffee schrieb:

    Ich habe nämlich vier Views, jeweils als UserControl: SucheView.xaml, PlattendecksView.xaml, Equalizer View. xaml und SettingsView.xaml.
    Dann leg 4 DataTemplates in die Resourcen des ContentPresenters. - für jeden ViewmodelTyp einen.
    Die angebundene Viewmodel-List muss dann logischerweise Viewmodelse verschiedener Typen beinhalten - am besten haben diese Viewmodelse einen gemeinsamen Basistyp.

    VB.NET-Quellcode

    1. class myVMBase
    2. end class
    3. class myVM1:inherits myVMBase
    4. end class
    5. class myVM2:inherits myVMBase
    6. end class
    7. class myVM3:inherits myVMBase
    8. end class
    9. class myVM4:inherits myVMBase
    10. end class
    11. class MainViewmodel
    12. '...
    13. private Readonly _myVMs as new list(Of myVMBase)
    14. publich Property myVMs As new ListcollectionView (_myVMs)
    15. end class
    so in die Richtung.
    @ErfinderDesRades

    Boah hey sei mir nicht böse, ich knabber grad noch an mindestens drei andern Problemen rum. Hab da jetzt grad net den Schädel zu.

    Aber bei Gelegenheit komme ich gern drauf zurück, jetzt bin ich schon bissle neugierig geworden.

    Kannst du mir vielleicht ne konkrete Antwort auf die Frage in Post1 geben? Ich mein das Konzept ist bisher aufgegangen, bis ich angefangen hab, meine Registerkarten aus der MainWindow.xaml als Benutzersteuerelemente zu extrahieren...

    Als ersten Schritt kannste mir ja gern ein Contentpresenter Tut ans Herz legen, hab nämlich noch nie mit einem gearbeitet. Dann kann ich das in ner freien Minute erstmal durchgehen... Um mal die Grundlagen erst zu haben...

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „kafffee“ ()

    Die Frage in post#1 lautet:

    kafffee schrieb:

    Was mache ich falsch?
    Und bezieht sich vermutlich, warum iwelche Intellisense nicht richtig anzeigt.
    Jo - weiss ich nicht.

    ContentPresenter-Tut weiss ich grad nicht wo - mir ist, als hätte ich das schoma bearbeitet - im Zusammenhang mit wpf-TabControl.
    Weiss aber nicht mehr wo.
    Jo, vlt mach ich mal ein Zusatz-Post im 4-View-Tut.
    Vielleicht löst du das einfach so, dass du in deiner Code-Behind Datei für jedes deiner Views ein Boolean hinzufügst, in etwa so:

    VB.NET-Quellcode

    1. ​Dim IsSucheVisible As Boolean
    2. Dim IsPlattendecksVisible As Boolean
    3. ...


    und in deinen Views setzt du Visiblility als Binding an genau diese vier Variablen.

    Dann kannst du im Code-Behind einfach steuern:

    IsSucheVisible = true. Der Rest passiert dann automatisch. Falls ich das richtig verstanden habe
    @PadreSperanza

    Ich probier jetzt erstmal die Methode von ErfinderDesRades, wenn das nicht ohne grösseren Aufwand funktioniert, probier ich deins auch mal. Bei deiner Methode müsste ich glaube ich auf den ersten Blick aber auch noch einen Converter einsetzen, um

    XML-Quellcode

    1. Visibiity.Hidden
    in

    XML-Quellcode

    1. False
    umzuwandeln usw...

    @ErfinderDesRades

    Guck mal, DataTemplate hab ich mir folgendes ausgedacht (jedes ViewModel bekommt dann noch eine Property Highlightfarbe und Icon):

    Wie findest dus?

    XML-Quellcode

    1. <ListBox Name="lstNavigationsleiste" ItemsSource="{Binding Meine4ViewModels}" SelectionMode="Single" IsSelected="{Binding GezeigteRegisterkarte}>
    2. <ListBox.ItemTemplate>
    3. <DataTemplate>
    4. <Border Name="brdPlaylist" Style="{DynamicResource Navigationsbuttons}">
    5. <Grid>
    6. <Grid.ColumnDefinitions>
    7. <ColumnDefinition Width="5*"/>
    8. <ColumnDefinition Width="95*"/>
    9. </Grid.ColumnDefinitions>
    10. <Rectangle Name="icoHighlight" Grid.Column="0" Style="{DynamicResource NavigationsHighlight}" Fill="{Binding Highlightfarbe}"/>
    11. <Canvas Grid.Column="1" Name="icoContent" Style="{StaticResource Navigationssymbol}">
    12. <Path Fill="{DynamicResource VordergrundfarbeBrush}" Data="{Binding Icon}"/>
    13. </Canvas>
    14. </Grid>
    15. </Border>
    16. </DataTemplate>
    17. </ListBox.ItemTemplate>
    18. </ListBox>


    Jetzt bin ich auch mal gespannt auf dein ContentPresenter-Tut....

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „kafffee“ ()

    @ErfinderDesRades

    Hab jetzt folgendes in der Application.xaml:

    XML-Quellcode

    1. <Style x:Key="Hauptregister" TargetType="ContentPresenter">
    2. <Style.Triggers>
    3. <DataTrigger Binding="{Binding SelektierteRegisterkarte}" Value="0">
    4. <Setter Property="ContentTemplate" Value="{StaticResource resSuche}"/>
    5. </DataTrigger>
    6. <DataTrigger Binding="{Binding SelektierteRegisterkarte}" Value="1">
    7. <Setter Property="ContentTemplate" Value="{StaticResource resPlattendecks}"/>
    8. </DataTrigger>
    9. <DataTrigger Binding="{Binding SelektierteRegisterkarte}" Value="2">
    10. <Setter Property="ContentTemplate" Value="{StaticResource resEqualizer}"/>
    11. </DataTrigger>
    12. <DataTrigger Binding="{Binding SelektierteRegisterkarte}" Value="3">
    13. <Setter Property="ContentTemplate" Value="{StaticResource resSettings}"/>
    14. </DataTrigger>
    15. </Style.Triggers>
    16. </Style>
    17. <DataTemplate x:Key="resSuche">
    18. <View:Suche/>
    19. </DataTemplate>
    20. <DataTemplate x:Key="resPlattendecks">
    21. <View:PlattendecksView/>
    22. </DataTemplate>
    23. <DataTemplate x:Key="resEqualizer">
    24. <View:EqualizerView/>
    25. </DataTemplate>
    26. <DataTemplate x:Key="resSettings">
    27. <View:SettingsView/>
    28. </DataTemplate>


    So sieht meine MainWindow.xaml aus:

    XML-Quellcode

    1. <Window
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    6. xmlns:View="clr-namespace:VamosALaPlayer_3._0.View;assembly=VamosALaPlayer_3._0.View" x:Class="MainWindow"
    7. mc:Ignorable="d"
    8. xmlns:viewmodel="clr-namespace:VamosALaPlayer_3._0.App"
    9. Title="VamosALaPlayer 3.0" Height="450" Width="800" Style="{StaticResource meinstil}" Loaded="Window_Loaded">
    10. <Window.DataContext>
    11. <viewmodel:Application/>
    12. </Window.DataContext>
    13. <Grid Name="grdHauptseite" Style="{StaticResource MeinGrid}">
    14. <Grid.ColumnDefinitions>
    15. <ColumnDefinition Width="5*"/>
    16. <ColumnDefinition Width="95*"/>
    17. </Grid.ColumnDefinitions>
    18. <View:Navigationsleiste Grid.Column="0"/>
    19. <ContentPresenter Name="Hauptregister" Style="{DynamicResource Hauptregister}" Grid.Column="1"/>
    20. </Grid>
    21. </Window>


    Schon besser oder?

    kafffee schrieb:

    Ich probier jetzt erstmal die Methode von ErfinderDesRades, wenn das nicht ohne grösseren Aufwand funktioniert, probier ich deins auch mal. Bei deiner Methode müsste ich glaube ich auf den ersten Blick aber auch noch einen Converter einsetzen, um
    XML-Quellcode
    Visibiity.Hidden
    in
    XML-Quellcode
    False
    umzuwandeln usw...


    stimmt.

    Oder du setzt statt vier Boolean direkt vier Variablen ein, die vom Typ Visbility sind.

    Dann setzt du statt auf true/false auf visible/hidden/collapsed. Geht auch ;)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „PadreSperanza“ ()

    @ErfinderDesRades Ja schon, bei mir ist das Szenario aber glaube ich ein bisschen anders. Ich habe vier gänzlich verschiedene Views in vier verschiedenen Dateien, die so rein gar nichts miteinander zu tun haben. Also fand ich diese Lösung naheliegend...

    Hatte dann beim Kompilieren erstmal 69 Fehler, bin jetzt auf 41 runter... Sind wahrscheinlich aber nur 2 oder 3 mit "Folgefehlern" denke ich. Das meiste wird wohl daran liegen, dass ich die Application.xaml und Mainwindow.xaml glaub ich fälschlicherweise nicht im View-Projekt sondern im App-Projekt erstellt hab (ich benutze die Projektvorlage von @Nofear23m ) und ist mein erster MVVM-Versuch und irgendwelche Probleme mit Namespaces hab. Aber muss ich mir mal noch genauer anschauen...

    kafffee schrieb:

    bei mir ist das Szenario aber glaube ich ein bisschen anders.
    Nö.
    Zumindest nach dem, was du bisher erklärt hast, nicht.

    Aber deine Denke steht dir immernoch total im Weg:

    kafffee schrieb:

    Ich habe vier gänzlich verschiedene Views in vier verschiedenen Dateien
    Du bist offsichtlich immer noch nicht bei MVVM angekommen.
    Weil was du für Views hast ist eher irrelevant.
    Relevant ist das ViewModel - und was soll das Problem sein, vier unterschiedliche Viewmodels zu haben?
    Und zu jedem Viewmodel baut man ein DataTemplate - fertig sind "vier gänzlich verschiedene Views".

    Und in "vier verschiedene Dateien" - naja, ich mach immer ein UserControl je Viewmodel - je in eine Datei.
    Dadurch werden Styles und DataTemplates sehr einfach:

    XML-Quellcode

    1. <DataTemplate DataType="{x:Type vm:myViewmodel1">
    2. <vw:myView1/>
    3. </DataTemplate>




    Hmm - jetzt sehe ich, dass du das ja eiglich in post#11 schon (fast) hast.
    Nur hampelst du dann da mit einem ContentPresenter-Style herum, was ganz unnötig ist.
    Wenn du ins Tut guckst: Ein ContentPresenter findet das richtige Template selber - er braucht dafür keinen Style.
    Das DataTemplate muss allerdings den Datatype angeben, für den es ein Template sein soll. Dieses klein Detail fehlt bei dir.

    Und bitte hör auf, deine Controls mit Namen zu versehen.
    Namen braucht man nur für CodeBehind (was Gott verhindern möge!). Oder für ElementBindings (was dir bislang erspart geblieben ist)



    Ah - ich seh, du hast das Tut-Sample noch nichtmal runtergeladen, ok.
    Also mach erstmal den Stiefel so weit fertig auf dem Weg, wo du grad unterwegs bist - mit der NoFear-Projektvorlage etc.
    Kannst ja iwann drauf zurückkommen...

    Hat ja nicht unbedingt Sinn in zwei Richtungen gleichzeitig zu rennen.

    Dieser Beitrag wurde bereits 8 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Kleiner Tipp von mir (solltest du aber bereits wissen)

    Wenn du nicht weiterkommst am besten immer in einem frischen Projekt probieren.
    Mach ein neues Projekt mit Hilfe meiner Projektvorlage. Pack dort ein paar Controls in deine View rein so wie du diese benötigst. Muss ja nicht schön sein, einfach zum probieren.

    Ein ViewModel erstellen und hier mal die Eigenschaften definieren die du brauchst und versuchen das ins laufen zu bekommen. Klappt das nicht lade es hoch mit einer kleinen kurzen Beschreibung was denn wann wie passieren soll.
    Dann können wir dich an die Hand nehmen. Du solltest aber dennoch mal versuchen Binding zu verstehen.
    Wenn du fragen hast, dann frag.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    ErfinderDesRades schrieb:

    Hat ja nicht unbedingt Sinn in zwei Richtungen gleichzeitig zu rennen.


    Ja das denk ich auch. Ich probiers jetzt erstmal so wie ich bereits angefangen hab in Post 11.

    Wenn ich das Programm aber starte und in der Navigationsleiste ein Item aus der Listbox auswähle, passiert im ContentPresenter gar nichts... Obwohl richtig an SelektierteRegisterkarte gebunden. Das hab ich überprüft, wenn ich in der Appllication.xaml in Zeile 3 mit der Mouse drüber hovere wird der jeweilige SelectedIndex angezeigt...
    Also hab ich mal testweise in Zeile 2 folgendes eingefügt:

    <Setter Property="ContentTemplate" Value="{StaticResource resSuche}"/>

    Dann kommt der Fehler:

    System.Windows.Markup.XamlParseException
    HResult=0x80131501
    Nachricht = Zeilennummer "18" und Zeilenposition "27" von "Beim Festlegen der Eigenschaft "System.Windows.FrameworkElement.Style" wurde eine Ausnahme ausgelöst.".
    Quelle = PresentationFramework
    Stapelüberwachung:
    bei System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
    bei System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri)
    bei System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream)
    bei System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
    bei VamosALaPlayer_3._0.App.MainWindow.InitializeComponent() in F:\Programme\VALP 3.0\VamosALaPlayer 3.0\VamosALaPlayer 3.0\VamosALaPlayer_3._0.App\MainWindow.xaml: Zeile1

    Innere Ausnahme 1:
    InvalidCastException: Das Objekt des Typs "MS.Internal.NamedObject" kann nicht in Typ "System.Windows.DataTemplate" umgewandelt werden.
    Mach das bitte mit einem ContenControl und binde dessen Conent Eigenschaft auf deine Eigenschaft in der ViewModel Klasse. Da brauchste keinen Setter in einem Style oder sonstwas. Einfach Cintent binden und gut is.

    Grüße
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Bin gerade dabei, im Contentcontrol die DataTemplates festzulegen. Leider hab ich ein Problem mit den Namespaces und weiss nicht, wie ich das beheben soll. Man sieht alles sehr schön auf dem Screeenshot. Ich gehe davon aus, dass ich einfach die MainWindow.xaml in die View kopieren muss und dann im ViewModel eine MainWindowViewModel erstellen muss, liege ich da richtig?
    Bilder
    • screenshot-namepsaces.png

      267 kB, 2.560×1.080, 46 mal angesehen
    wenn ich das richtig sehe, dann liegt "SucheViewModel" im Namespace VamosALaPlayer_3_0.ViewModel (rechts im Bild geschaut).

    Du referenzierst aber "viewmodel:" mit VamosALaPlayer_3_0.App -> xmlns:viewmodel="clr-namespace:VamosAlaPlayer.App"

    Und in App hast du aber kein SucheViewModel. Also musst du den Namespace anpassen oder auf den neuen Namespace referenzieren

    ZB: mit xmlns:viewmodel="clr-namespace:VamosAlaPlayer.ViewModel"

    oder (falls du bereits mit ViewModel etwas tust) einen neuen Verweis hinzufügen:

    xmlns:sucheVM="clr-namespace:VamosAlaPlayer.ViewModel" und das so einbinden:

    ​<DataTemplate DataType={x:Type sucheVM:SucheViewModel}