Megosztás a következőn keresztül:


Elrendezés

Ez a témakör a Windows Presentation Foundation (WPF) elrendezési rendszerét ismerteti. A felhasználói felületek WPF-ben való létrehozásához elengedhetetlen az elrendezésszámítások módjának és időpontjának megértése.

Ez a témakör a következő szakaszokat tartalmazza:

Elemhatároló dobozok

Amikor a WPF elrendezésére gondol, fontos megérteni az összes elemet körülvevő határolókeretet. Az elrendezési rendszer által felhasznált egyes FrameworkElement elemek az elrendezésbe illesztett téglalapként tekinthetők meg. Az LayoutInformation osztály egy elem elrendezési lefoglalásának vagy pontjának határait adja vissza. A téglalap méretét a rendelkezésre álló képernyőterület, a korlátozások mérete, az elrendezés-specifikus tulajdonságok (például a margó és a párnázás) és a szülőelem Panel egyéni viselkedésének kiszámítása határozza meg. Ezeket az adatokat feldolgozva az elrendezési rendszer ki tudja számítani az adott Panel gyermekek helyzetét. Fontos megjegyezni, hogy a szülőelemen definiált méretezési jellemzők, például az a Border, hatással vannak a gyermekekre.

Az alábbi ábrán egy egyszerű elrendezés látható.

Egy tipikus rácsot ábrázoló képernyőkép, amely nem fedi fel a határolókeretet.

Ez az elrendezés az alábbi XAML használatával érhető el.

<Grid Name="myGrid" Background="LightSteelBlue" Height="150">
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="250"/>
  </Grid.ColumnDefinitions>
  <Grid.RowDefinitions>
    <RowDefinition />
    <RowDefinition />
    <RowDefinition />
  </Grid.RowDefinitions>
  <TextBlock Name="txt1" Margin="5" FontSize="16" FontFamily="Verdana" Grid.Column="0" Grid.Row="0">Hello World!</TextBlock>
  <Button Click="getLayoutSlot1" Width="125" Height="25" Grid.Column="0" Grid.Row="1">Show Bounding Box</Button>
  <TextBlock Name="txt2" Grid.Column="1" Grid.Row="2"/>
</Grid>

Egyetlen elem, a TextBlock, van egy Grid alatt üzemeltetve. Míg a szöveg csak az első oszlop bal felső sarkát tölti ki, a lefoglalt terület TextBlock valójában sokkal nagyobb. Bármely FrameworkElement határolókerete lekérhető a GetLayoutSlot függvény segítségével. Az alábbi ábrán a TextBlock elem határolókerete látható.

Képernyőkép arról, hogy a TextBlock határolókerete már látható.

Ahogy a sárga téglalap mutatja, az elem lefoglalt TextBlock területe valójában sokkal nagyobb, mint amilyennek látszik. A további elemek hozzáadásakor ez a Gridfoglalás a hozzáadott elemek típusától és méretétől függően zsugorodhat vagy bővülhet.

Az TextBlock elrendezési mező lefordítása Path-re a GetLayoutSlot módszer használatával történik. Ez a technika hasznos lehet egy elem határolókeretének megjelenítéséhez.

private void getLayoutSlot1(object sender, System.Windows.RoutedEventArgs e)
{
    RectangleGeometry myRectangleGeometry = new RectangleGeometry();
    myRectangleGeometry.Rect = LayoutInformation.GetLayoutSlot(txt1);
    Path myPath = new Path();
    myPath.Data = myRectangleGeometry;
    myPath.Stroke = Brushes.LightGoldenrodYellow;
    myPath.StrokeThickness = 5;
    Grid.SetColumn(myPath, 0);
    Grid.SetRow(myPath, 0);
    myGrid.Children.Add(myPath);
    txt2.Text = "LayoutSlot is equal to " + LayoutInformation.GetLayoutSlot(txt1).ToString();
}
Private Sub getLayoutSlot1(ByVal sender As Object, ByVal e As RoutedEventArgs)
    Dim myRectangleGeometry As New RectangleGeometry
    myRectangleGeometry.Rect = LayoutInformation.GetLayoutSlot(txt1)
    Dim myPath As New Path
    myPath.Data = myRectangleGeometry
    myPath.Stroke = Brushes.LightGoldenrodYellow
    myPath.StrokeThickness = 5
    Grid.SetColumn(myPath, 0)
    Grid.SetRow(myPath, 0)
    myGrid.Children.Add(myPath)
    txt2.Text = "LayoutSlot is equal to " + LayoutInformation.GetLayoutSlot(txt1).ToString()
End Sub

Az elrendezési rendszer

A legegyszerűbb elrendezés egy rekurzív rendszer, amely egy méretezhető, elhelyezett és rajzolt elemet eredményez. Az elrendezés pontosabban az Panel elem Children gyűjtemény tagjainak mérésének és rendezésének folyamatát ismerteti. Az elrendezés intenzív folyamat. Minél nagyobb a Children gyűjtemény, annál több számítást kell elvégezni. Az összetettség a gyűjtemény tulajdonoseleme által Panel meghatározott elrendezési viselkedés alapján is bevezethető. A viszonylag egyszerű Panel, például Canvasa teljesítmény jelentősen jobb lehet, mint egy összetettebb Panel, például Grid.

Minden alkalommal, amikor egy gyermek UIElement megváltoztatja a pozícióját, lehetősége van új frissítést kiváltani az elrendezési rendszerben. Ezért fontos megérteni azokat az eseményeket, amelyek meghívhatják az elrendezési rendszert, mivel a szükségtelen meghívás rossz alkalmazásteljesítményhez vezethet. Az alábbiakban az elrendezési rendszer meghívásakor előforduló folyamatot mutatjuk be.

  1. A gyermek UIElement elrendezési folyamata úgy kezdődik, hogy először az alapvető tulajdonságait mérik meg.

  2. A rendszer kiértékeli a FrameworkElement megadott méretezési tulajdonságokat, például Width: , Heightés Margin.

  3. Panel-specifikus logikát alkalmazunk, például Dock irányt vagy halmozást Orientation.

  4. A tartalom elrendezése az összes gyermek mérése után történik.

  5. A Children gyűjtemény a képernyőn lesz rajzolva.

  6. A rendszer újra meghívja a folyamatot, ha a rendszer további Children elemeket ad hozzá a gyűjteményhez, alkalmaz egy LayoutTransform alkalmazást, vagy meghívja a UpdateLayout metódust.

Ezt a folyamatot és a meghívás módját részletesebben az alábbi szakaszok határozzák meg.

Gyermekek mérése és rendezése

Az elrendezési rendszer két bérletet hajt végre a Children gyűjtemény minden egyes tagjára vonatkozóan, egy mértékbérletet és egy elrendezési bérletet. Minden gyermek Panel saját MeasureOverride és ArrangeOverride metódusokat biztosít a saját elrendezési viselkedésének eléréséhez.

A mérték áthaladása során a rendszer kiértékeli a Children gyűjtemény minden tagját. A folyamat a Measure metódus hívásával kezdődik. Ezt a metódust a szülőelem Panel implementálásán belül hívjuk meg, és nem kell explicit módon meghívni az elrendezéshez.

Először a rendszer kiértékeli a UIElement natív mérettulajdonságokat, például Clip és Visibility. Ez létrehoz egy értéket constraintSize , amelyet a rendszer átad a rendszernek MeasureCore.

Másodszor feldolgozzák a keretrendszer FrameworkElement-en definiált tulajdonságait, amelyek hatással vannak a constraintSize értékére. Ezek a tulajdonságok általában az alapul szolgáló UIElement méretbeli jellemzőit írják le, mint például a Height, Width, Margin és Style. Ezek a tulajdonságok módosíthatják az elem megjelenítéséhez szükséges területet. MeasureOverride ezután meghívja a constraintSize-t paraméterként.

Megjegyzés:

Különbség van Height és Width, valamint ActualHeight és ActualWidth tulajdonságai között. A ActualHeight tulajdonság például egy számított érték, amely az egyéb magassági bemenetek és az elrendezési rendszer alapján lett meghatározva. Az értéket maga az elrendezési rendszer állítja be egy tényleges renderelési áthaladás alapján, ezért kissé elmaradhat a bemeneti változás alapjául szolgáló tulajdonságok beállított értékétől, például Height.

Mivel ActualHeight számított értékről van szó, tisztában kell lennie azzal, hogy az elrendezési rendszer különböző műveleteinek eredményeként több vagy növekményes jelentett módosítás is előfordulhat. Az elrendezési rendszer kiszámíthatja a gyermekelemekhez szükséges mértéktartományt, a szülőelem korlátait stb.

A mérték átadásának végső célja az, hogy a gyermek meghatározza a DesiredSize, amely a MeasureCore hívás során történik meg. A DesiredSize értéket a Measure rendszer a tartalom elrendezési fázisában tárolja felhasználásra.

Az elrendezési lépés a Arrange metódus hívásával kezdődik. Az elrendezési folyamat során a szülőelem Panel létrehoz egy téglalapot, amely meghatározza a gyermek határait. Ez az érték a feldolgozáshoz használt metódusnak lesz átadva ArrangeCore .

A ArrangeCore módszer kiértékeli a DesiredSize gyermek értékét, és kiértékeli az elem renderelt méretét esetlegesen befolyásoló további margókat. ArrangeCore létrehoz egy arrangeSize, amelyet a rendszer átad a ArrangeOverridePanel paraméter metódusának. A gyermek ArrangeOverride-ét generálja finalSize. Végül az eljárás elvégzi az ArrangeCore eltolási tulajdonságok, például a margó és az igazítás végső kiértékelését, majd a gyermek az elrendezési pozícióba kerül. A gyermeknek nem kell (és gyakran nem) kitöltenie a teljes lefoglalt területet. A vezérlő ezután visszakerül a szülőhöz Panel , és az elrendezési folyamat befejeződött.

Panelelemek és egyéni elrendezési viselkedések

A WPF tartalmaz egy olyan elemcsoportot, amely a következőből Panelszármazik: . Ezek az Panel elemek számos összetett elrendezést tesznek lehetővé. Az elemek halmozása például egyszerűen megvalósítható az StackPanel elem használatával, míg az összetettebb és szabadabb elrendezések a Canvas elem használatával lehetségesek.

Az alábbi táblázat összefoglalja a rendelkezésre álló elrendezési Panel elemeket.

Panel neve Leírás
Canvas Meghatároz egy területet, amelyen belül a gyermekelemeket az Canvas területhez viszonyított koordináták alapján explicit módon helyezheti el.
DockPanel Meghatározza azt a területet, amelyen belül vízszintesen vagy függőlegesen egymáshoz viszonyítva rendezheti a gyermekelemeket.
Grid Egy rugalmas rácsterületet határoz meg, amely oszlopokból és sorokból áll.
StackPanel A gyermekelemeket egyetlen sorba rendezi, amely vízszintesen vagy függőlegesen is tájolható.
VirtualizingPanel Keretrendszert biztosít a gyermekadat-gyűjtést virtualizáló elemekhez Panel . Ez egy absztrakt osztály.
WrapPanel A gyermekelemeket sorrendben helyezi el balról jobbra, és a tartalom a következő sorba kerül a tartalmazó doboz szélén. A későbbi rendezés sorrendben történik felülről lefelé vagy jobbról balra, a Orientation tulajdonság értékétől függően.

Azokban az alkalmazásokban, amelyek olyan elrendezést igényelnek, amelyet egyik előre definiált Panel elem használatával sem lehet megvalósítani, az egyéni elrendezési viselkedéseket úgy érhetjük el, hogy öröklünk a Panel osztályból, majd felülírjuk a MeasureOverride és ArrangeOverride metódusokat.

Elrendezés teljesítményével kapcsolatos szempontok

Az elrendezés rekurzív folyamat. A Children gyűjtemény minden gyermekeleme feldolgozásra kerül az elrendezési rendszer minden meghívása során. Ennek eredményeképpen az elrendezési rendszer aktiválását el kell kerülni, ha nincs rá szükség. Az alábbi szempontok segíthetnek a jobb teljesítmény elérésében.

  • Vegye figyelembe, hogy mely tulajdonságérték-módosítások kényszerítik az elrendezési rendszer rekurzív frissítését.

    Azok a függőségi tulajdonságok, amelyek értékei az elrendezési rendszer inicializálását okozhatják, nyilvános jelzőkkel vannak megjelölve. AffectsMeasure és AffectsArrange hasznos tanácsokat ad arról, hogy mely tulajdonságértékek változásai kényszerítik az elrendezési rendszer rekurzív frissítését. Általánosságban elmondható, hogy minden olyan tulajdonságnak, amely befolyásolhatja egy elem határolókeretének méretét, a AffectsMeasure jelölőnek igaznak kell lennie. További információ: Függőség tulajdonságainak áttekintése.

  • Ha lehetséges, használjon RenderTransform-t a LayoutTransform helyett.

    A LayoutTransform nagyon hasznos eszköz lehet a felhasználói felület (UI) tartalmának befolyásolására. Ha azonban az átalakítás hatásának nem kell befolyásolnia más elemek pozícióját, érdemes helyette használni, RenderTransform mert RenderTransform nem hívja meg az elrendezési rendszert. LayoutTransform az átalakítást alkalmazza, és rekurzív elrendezésfrissítést kényszerít ki az érintett elem új pozíciójának figyelembe vételéhez.

  • Kerülje a szükségtelen hívásokat.UpdateLayout

    A UpdateLayout metódus rekurzív elrendezésfrissítést kényszerít ki, és gyakran nem szükséges. Ha nem biztos abban, hogy teljes frissítés szükséges, hagyatkozzon az elrendezési rendszerre, hogy a módszert meghívja ön helyett.

  • Ha nagy Children gyűjteményt használ, fontolja meg a VirtualizingStackPanel normál StackPanel helyett a használatát.

    A gyermekgyűjtemény virtualizálásával az VirtualizingStackPanel egyetlen olyan objektum marad a memóriában, amely jelenleg a szülő ViewPortjában található. Ennek eredményeképpen a legtöbb forgatókönyvben jelentősen javul a teljesítmény.

Szubpixeles megjelenítés és elrendezés kerekítése

A WPF grafikus rendszer eszközfüggetlen egységeket használ a felbontás és az eszköz függetlenségének engedélyezéséhez. Minden eszközfüggetlen képpont automatikusan skálázódik a rendszer pont/hüvelyk (dpi) beállításával. Ez megfelelő skálázást biztosít a WPF-alkalmazások számára a különböző dpi-beállításokhoz, és automatikusan dpi-tudatossá teszi az alkalmazást.

Ez a dpi-függetlenség azonban szabálytalan élmegjelenítést okozhat az élsimítás miatt. Ezek az összetevők, amelyek általában homályos vagy félig átlátszó éleknek tekinthetők, akkor fordulhatnak elő, ha az él helye az eszköz képpontjai közé esik, nem pedig az eszköz képpontjai közé. Az elrendezési rendszer lehetővé teszi, hogy ehhez az elrendezés kerekítésével igazodjon. Az elrendezési kerekítés az a folyamat, amely során az elrendezési rendszer kerekíti a nem egész számú képpontértékeket az elrendezési folyamat során.

Az elrendezés kerekítése alapértelmezés szerint le van tiltva. Az elrendezés kerekítésének engedélyezéséhez állítsa a UseLayoutRounding tulajdonságot true bármely FrameworkElement-nél. Mivel ez egy függőségi tulajdonság, az érték a vizualizációfán lévő összes gyermekre propagálódik. A teljes felhasználói felületen az elrendezés kerekítésének engedélyezéséhez állítsa be a gyökértároló UseLayoutRounding értékét true-ra. Példaként tekintse meg a UseLayoutRounding-t.

Mi a következő lépés?

Az elrendezés megértésének első lépése az elemek mérésének és elrendezésének megértése. Az elérhető Panel elemekről további információt a Panelek áttekintése című témakörben talál. Az elrendezést befolyásoló különböző elhelyezési tulajdonságok jobb megismeréséhez tekintse meg az Igazítás, a Margók és a Kitöltés áttekintése című témakört. Ha készen áll arra, hogy mindezt egy egyszerűsített alkalmazásba helyezze, tekintse meg az útmutatót: Az első asztali WPF-alkalmazásom.

Lásd még