none
User Control ContentControl non riempie spazi vuoti RRS feed

  • Domanda

  • [UWP] ciao a tutti, sono alle prese con un usercontrol, ho creato un mio contentirore di campo (groupbox) dove all'interno inseriscoo diversi stacpanel con all'interno delle textbox.

    ma quando inserisco le stackpanel non vengono visualizzata riempiendo tutto lo spazio vuoto. Ho provato a settare strecth nelle varie opzioni ma nulla.

    questo è il codice del mio usercontrol:

    <UserControl Name="groupBoxUC"
        x:Class="AgendaUWP.Common.CustomControls.GroupBox"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:AgendaUWP.Common.CustomControls"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:interop="using:Windows.UI.Xaml.Interop"
        mc:Ignorable="d"
        d:DesignHeight="200"
        d:DesignWidth="300">
    
            <StackPanel x:Name="myStackPanel"  BorderThickness="1" BorderBrush="Gray" Orientation="Vertical">
            <StackPanel Margin="10 0 0 0"   HorizontalAlignment="Left" >
                <Border  Background="{StaticResource secondaryColor}"  Height="5" Width="{Binding ActualWidth, ElementName=HeaderText}"/>
                <TextBlock x:Name="HeaderText" FontSize="18" FontWeight="ExtraLight"   Text="{x:Bind Header,Mode=TwoWay}"/>
            </StackPanel>
    
            <ContentControl Padding="10 20 10 20"  Content="{Binding InnerContent,ElementName=groupBoxUC}" HorizontalAlignment="Stretch" 
                    VerticalAlignment="Stretch" 
                    HorizontalContentAlignment="Stretch" 
                    VerticalContentAlignment="Stretch" />
        </StackPanel>
    
    </UserControl>

    e questo è come lo utilizzo:

                    <CustomControls:GroupBox x:Name="grpDatiAnagrafici" Header="Dati Anagrafici" VerticalAlignment="Top" Margin="30,0,30,0" Grid.Column="0" Grid.Row="0" >
    
                    <StackPanel x:Name="stkDatiAnagrafici" Orientation="Horizontal">
                        <StackPanel Padding="0 0 20 0">
                            <TextBox  Header="Codice:" Text="{x:Bind ViewModel.Cliente.Codice, Mode=TwoWay}" IsReadOnly="True" IsEnabled="False"/>
                            <TextBox  Header="Ragione Sociale:" Text="{x:Bind ViewModel.Cliente.RagioneSociale, Mode=TwoWay}"  />
                            <TextBox Header="Nome:" Text="{x:Bind ViewModel.Cliente.Nome, Mode=TwoWay}" />
                            <TextBox Header="Cognome:" Text="{x:Bind ViewModel.Cliente.Cognome, Mode=TwoWay}" />
                        </StackPanel>
                        <StackPanel>
                            <TextBox Header="Indirizzo:" Text="{x:Bind ViewModel.Cliente.Indirizzo, Mode=TwoWay}"  />
                            <TextBox Header="Comune:" Text="{x:Bind ViewModel.Cliente.Comune, Mode=TwoWay}" />
                            <TextBox Header="Cap:" Text="{x:Bind ViewModel.Cliente.Cap, Mode=TwoWay}" />
                            <TextBox Header="Provincia:" Text="{x:Bind ViewModel.Cliente.Provincia, Mode=TwoWay}" />
    
                        </StackPanel>
                    </StackPanel>
                </CustomControls:GroupBox>

    il mio risultato è il seguente

    Ovviamente con GridColumn definition, funziona, però siccome ho settato il VisualStateManager  per poter far vedere il secondo stacpanel in basso al primo, utilizzando le stackpanel basta solo cambiare l'orientamente, invece gestendo la grid con column definition, bisogna gestire anche le column.row quando viene visualizzato in un dispositivo mobile

    • Modificato brux88 sabato 22 ottobre 2016 11:39
    venerdì 21 ottobre 2016 07:39

Risposte

  • Ciao brux88,

    lo StackPanel può adattare il proprio contenuto solo nella direzione inversa rispetto alla sua proprietà Orientation, per capirci, se Orientation è impostata su Horizontal, i controlli al suo interno possono sfruttare solo il layout verticale tramite la proprietà VerticalAlignment. Questo è proprio il comportamento dello StackPanel e, avendo tu inserito il tutto all'interno di uno orientato orizzontalmente, non hai a disposizione nessun controllo sul layout orizzontale del contenuto che si "adatta al minimo" (come avrai notato la larghezza delle TextBox è basata sulla massima larghezza delle TextBlock, ad es. Ragione Sociale per la prima colonna e Provincia per la seconda colonna). Potresti allora andare a modificare manualmente la larghezza delle TextBox in modo che "riempiano" la visuale ma non è la scelta giusta a mio avviso, anche in considerazione che la disposizione sarà diversa a seconda del dispositivo. Risolveresti mettendo tutto in una grid con le colonne e gestire il layout col VisualStateManager ma anche questo è un metodo che sconsiglio, in realtà il vero errore sta proprio nel tuo approccio, ti spiego meglio, utilizzare due StackPanel per gestire il contenuto è sbagliato, le TextBox rappresentano le proprietà della classe Cliente e dovrebbero essere inserite all'interno di un unico controllo che ne gestisca poi il layout. Dico questo perché magari avrai la necessità di aggiungere una nuova proprietà alla classe Cliente e allora dovresti manualmente inserire altri campi e cambiare il codice per gestirne la posizione all'interno della visuale, e ciò ti farebbe perdere un sacco di tempo. Il mio consiglio è quello di avere un unico controllo dove all'interno inserirai le TextBox (o meglio, tanti StackPanel contenenti l'accoppiata TextBlock-TextBox) e far gestire a questo i layout e l'adattamento alla visuale. Quello che vuoi ottenere è qualcosa di abbastanza anomalo se ho capito bene, in un dispositivo mobile i campi vanno uno sotto all'altro mentre su un pc andranno sempre uno sotto l'altro ma quando si raggiunge il fondo della pagina i successivi vengono arrangiati in altre colonne le quali però dovranno essere equamente distribuite nell'intera larghezza della visuale. Potresti semplicemente usare un ItemsControl normale per la visualizzazione in un telefono, mentre per un pc cambiare il tipo di Panel utilizzato dall'ItemsControl per arrangiare gli elementi (proprietà ItemsPanel dell'ItemsControl). Non credo ci sia un Panel predefinito per ottenere esattamente il risultato che vuoi e dovresti crearne uno tu scrivendo una classe che erediti da Panel e che gestisca le dimensioni e le posizioni degli elementi figlio. Siccome non è semplicissimo il mio consiglio è di utilizzare la WrapGrid già presente nell'SDK, ti basterà sostituire il ContentControl con:

    <ItemsControl>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapGrid />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>

    Ti ricordo ancora che in questo caso la proprietà ItemsPanel va settata solo su pc e non su dispositivo mobile. Ovviamente, ti ripeto, non avrai il contenuto "spalmato" nell'intera visualizzazione però così a mio parere è meglio, dai una larghezza fissa alle caselle di testo e hai fatto. Se poi corri il rischio che qualcosa vada a finire oltre la finestra a destra, metti l'ItemsControl in uno ScrollViewer e potrai scrollarne il contenuto.

    Spero di esserti stato di aiuto.


    Gianluca Concilio

    • Contrassegnato come risposta brux88 sabato 22 ottobre 2016 19:40
    sabato 22 ottobre 2016 13:12

Tutte le risposte

  • Ciao brux88,

    lo StackPanel può adattare il proprio contenuto solo nella direzione inversa rispetto alla sua proprietà Orientation, per capirci, se Orientation è impostata su Horizontal, i controlli al suo interno possono sfruttare solo il layout verticale tramite la proprietà VerticalAlignment. Questo è proprio il comportamento dello StackPanel e, avendo tu inserito il tutto all'interno di uno orientato orizzontalmente, non hai a disposizione nessun controllo sul layout orizzontale del contenuto che si "adatta al minimo" (come avrai notato la larghezza delle TextBox è basata sulla massima larghezza delle TextBlock, ad es. Ragione Sociale per la prima colonna e Provincia per la seconda colonna). Potresti allora andare a modificare manualmente la larghezza delle TextBox in modo che "riempiano" la visuale ma non è la scelta giusta a mio avviso, anche in considerazione che la disposizione sarà diversa a seconda del dispositivo. Risolveresti mettendo tutto in una grid con le colonne e gestire il layout col VisualStateManager ma anche questo è un metodo che sconsiglio, in realtà il vero errore sta proprio nel tuo approccio, ti spiego meglio, utilizzare due StackPanel per gestire il contenuto è sbagliato, le TextBox rappresentano le proprietà della classe Cliente e dovrebbero essere inserite all'interno di un unico controllo che ne gestisca poi il layout. Dico questo perché magari avrai la necessità di aggiungere una nuova proprietà alla classe Cliente e allora dovresti manualmente inserire altri campi e cambiare il codice per gestirne la posizione all'interno della visuale, e ciò ti farebbe perdere un sacco di tempo. Il mio consiglio è quello di avere un unico controllo dove all'interno inserirai le TextBox (o meglio, tanti StackPanel contenenti l'accoppiata TextBlock-TextBox) e far gestire a questo i layout e l'adattamento alla visuale. Quello che vuoi ottenere è qualcosa di abbastanza anomalo se ho capito bene, in un dispositivo mobile i campi vanno uno sotto all'altro mentre su un pc andranno sempre uno sotto l'altro ma quando si raggiunge il fondo della pagina i successivi vengono arrangiati in altre colonne le quali però dovranno essere equamente distribuite nell'intera larghezza della visuale. Potresti semplicemente usare un ItemsControl normale per la visualizzazione in un telefono, mentre per un pc cambiare il tipo di Panel utilizzato dall'ItemsControl per arrangiare gli elementi (proprietà ItemsPanel dell'ItemsControl). Non credo ci sia un Panel predefinito per ottenere esattamente il risultato che vuoi e dovresti crearne uno tu scrivendo una classe che erediti da Panel e che gestisca le dimensioni e le posizioni degli elementi figlio. Siccome non è semplicissimo il mio consiglio è di utilizzare la WrapGrid già presente nell'SDK, ti basterà sostituire il ContentControl con:

    <ItemsControl>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapGrid />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>

    Ti ricordo ancora che in questo caso la proprietà ItemsPanel va settata solo su pc e non su dispositivo mobile. Ovviamente, ti ripeto, non avrai il contenuto "spalmato" nell'intera visualizzazione però così a mio parere è meglio, dai una larghezza fissa alle caselle di testo e hai fatto. Se poi corri il rischio che qualcosa vada a finire oltre la finestra a destra, metti l'ItemsControl in uno ScrollViewer e potrai scrollarne il contenuto.

    Spero di esserti stato di aiuto.


    Gianluca Concilio

    • Contrassegnato come risposta brux88 sabato 22 ottobre 2016 19:40
    sabato 22 ottobre 2016 13:12
  • grazie per la risposta sei stato chiarissimo, si in effetti non ha molto senso il layout e che sto iniziando a prendere mano con uwp, siccome ho sempre lavorato con wpf ( per utilizzando librerie di terze parti come devexpress, e il layout veniva gestito in maniera diversa, per questo ho difficolta ad utilizzare i controlli nativi dell xaml
    sabato 22 ottobre 2016 19:44