จะใช้ DockStyle.fill สำหรับการควบคุมมาตรฐานใน WPF ได้อย่างไร?


92

ฉันใช้จากแบบฟอร์ม windows ฉันสร้างแผงควบคุมวางแผงควบคุมไว้ข้างในและให้พวกเขาDockStyle.Fillขยายขนาดให้ใหญ่ที่สุดกับแผงรอบข้าง

ใน WPF ฉันต้องการมีเหมือนกัน ฉันมี TabControl และฉันต้องการให้ขนาดของมันกรอกแบบฟอร์มให้มากที่สุด ฉันมีตัวควบคุม Ribbon (RibbonControlsLibrary) และต้องการให้ส่วนที่เหลือของแบบฟอร์มเต็มไปด้วย TabControl ที่ขนาดสูงสุด

(ฉันไม่ต้องการเชื่อมต่อการควบคุมเช่นการเชื่อมต่อใน Visual Studio เพียงกลไกการเชื่อมต่อแบบเก่า)

คำตอบ:


181

WPF เทียบเท่ากับ DockStyle.Fill ของ WinForms คือ:

HorizontalAlignment="Stretch" VerticalAlignment="Stretch"

นี่เป็นค่าเริ่มต้นสำหรับตัวควบคุมเกือบทั้งหมดดังนั้นโดยทั่วไปคุณไม่ต้องทำอะไรเลยเพื่อให้ตัวควบคุม WPF เติมคอนเทนเนอร์หลัก : พวกมันจะทำโดยอัตโนมัติ นี่เป็นเรื่องจริงสำหรับภาชนะทั้งหมดที่ไม่บีบเด็กให้มีขนาดต่ำสุด

ข้อผิดพลาดทั่วไป

ตอนนี้ฉันจะอธิบายข้อผิดพลาดทั่วไปหลายประการที่ทำให้ไม่สามารถHorizontalAlignment="Stretch" VerticalAlignment="Stretch"ทำงานได้ตามที่คาดไว้

1. ความสูงหรือความกว้างที่ชัดเจน

ข้อผิดพลาดทั่วไปประการหนึ่งคือการระบุความกว้างหรือความสูงอย่างชัดเจนสำหรับตัวควบคุม ดังนั้นหากคุณมีสิ่งนี้:

<Grid>
  <Button Content="Why am I not filling the window?" Width="200" Height="20" />
  ...
</Grid>

เพียงแค่ลบแอตทริบิวต์ความกว้างและความสูง:

<Grid>
  <Button Content="Ahhh... problem solved" />
  ...
</Grid>

2. แผงควบคุมจะบีบตัวควบคุมให้มีขนาดต่ำสุด

ข้อผิดพลาดทั่วไปอีกประการหนึ่งคือให้แผงควบคุมของคุณบีบตัวควบคุมให้แน่นที่สุดเท่าที่จะทำได้ ตัวอย่างเช่น StackPanel แนวตั้งมักจะบีบเนื้อหาในแนวตั้งให้เล็กที่สุดเท่าที่จะทำได้:

<StackPanel>
  <Button Content="Why am I squished flat?" />
</StackPanel>

เปลี่ยนเป็นแผงควบคุมอื่นแล้วคุณจะดีไป:

<DockPanel>
  <Button Content="I am no longer squished." />
</DockPanel>

นอกจากนี้แถวหรือคอลัมน์ของตารางที่มีความสูงเป็น "อัตโนมัติ" ก็จะบีบเนื้อหาไปในทิศทางนั้นเช่นเดียวกัน

ตัวอย่างภาชนะที่ไม่บีบเด็ก ได้แก่ :

  • ContentControls ไม่บีบเด็ก (รวมถึง Border, Button, CheckBox, ScrollViewer และอื่น ๆ อีกมากมาย)
  • ตารางที่มีแถวและคอลัมน์เดียว
  • ตารางที่มีแถวและคอลัมน์ขนาด "*"
  • DockPanel ไม่บีบลูกสุดท้าย
  • TabControl ไม่บีบเนื้อหา

ตัวอย่างภาชนะที่บีบเด็ก ได้แก่ :

  • StackPanel บีบในทิศทางการวางแนว
  • ตารางที่มีแถวหรือคอลัมน์ขนาด "อัตโนมัติ" บีบไปในทิศทางนั้น
  • DockPanel บีบทั้งหมดยกเว้นลูกสุดท้ายในทิศทางท่าเรือ
  • TabControl บีบส่วนหัว (สิ่งที่แสดงบนแท็บ)

3. ความสูงหรือความกว้างที่ชัดเจนออกไป

น่าทึ่งมากที่ฉันเห็น Grid หรือ DockPanel กี่ครั้งที่มีความสูงและความกว้างที่ชัดเจนเช่นนี้:

<Grid Width="200" Height="100">
  <Button Content="I am unnecessarily constrainted by my containing panel" />
</Grid>

โดยทั่วไปคุณไม่ต้องการกำหนดความสูงหรือความกว้างที่ชัดเจน ขั้นตอนแรกของฉันในการวินิจฉัยปัญหาการจัดวางคือการลบความสูงหรือความกว้างที่ชัดเจนทั้งหมดที่ฉันสามารถพบได้

4. Window คือ SizeToContent เมื่อไม่ควรเป็น

เมื่อคุณใช้ SizeToContent เนื้อหาของคุณจะถูกบีบให้มีขนาดต่ำสุด ในหลาย ๆ แอปพลิเคชันนี้มีประโยชน์มากและเป็นทางเลือกที่ถูกต้อง แต่ถ้าเนื้อหาของคุณไม่มีขนาด "ธรรมชาติ" คุณอาจต้องละเว้น SizeToContent


ฉันซ้ายค่อนข้างซับซ้อนคำถามที่เกี่ยวข้องกับรูปแบบใหม่ที่นี่ หลังจากอ่านคำตอบของคุณที่นี่ฉันคิดว่าคุณสามารถเข้าใจได้ Cheers
Berryl

7
ตอบโจทย์สุด ๆ ! ฉันหวังว่าฉันจะให้คะแนนโบนัสแก่คุณได้บ้าง :)
Jim Raden

@ Jim Raden: คุณสามารถเพิ่มรางวัลให้กับคำถามนี้และกำหนดคะแนนให้กับ Ray Burns;)
citronas

1
หมายเหตุด้านข้างสำหรับผู้อ่านในอนาคต: จะไม่อัปเดตในมุมมองออกแบบจนกว่าคุณจะคอมไพล์ใหม่
เดวิด

"<Button Content =" ทำไมฉันไม่เติมหน้าต่าง "width =" 200 "Height =" 20 "/>" ทำให้ฉันแตก! XD
Jack Frost

7

คุณสามารถทำในสิ่งที่ต้องการได้เพียงแค่พูดDockPanel LastChildFill="True"จากนั้นให้แน่ใจว่าสิ่งที่คุณต้องการเป็นฟิลเลอร์นั้นแท้จริงแล้วคือลูกคนสุดท้าย!

Grid เป็นรูปแบบสัตว์ร้ายที่คุณสามารถทำอะไรก็ได้เกือบทุกอย่าง แต่ DockPanel มักเป็นตัวเลือกที่เหมาะสมสำหรับแผงเค้าโครงด้านนอกสุดของคุณ นี่คือตัวอย่างรหัส psuedocode:

<DockPanel LastChildFill="True">
    <MyMenuBar DockPanel.Dock="Top"/>
    <MyStatus DockPanel.Dock="Bottom"/>

    <MyFillingTabControl />
</DockPanel>

5

เพียงแค่รวมการควบคุมของคุณในตารางด้วยสองแถว ตารางจะใช้พื้นที่ทั้งหมดที่กำหนดให้โดยอัตโนมัติและคุณสามารถกำหนดแถวเพื่อใช้พื้นที่ทั้งหมดที่เหลือได้โดยให้ความสูงเป็น "*" แถวแรกในตัวอย่างของฉัน (ความสูง = "อัตโนมัติ") จะใช้พื้นที่เท่าที่ริบบิ้นต้องการ หวังว่าจะช่วยได้

<Grid>
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="*" />
  </Grid.RowDefinitions>

  <Ribbon Grid.Row="0" />

  <TabPage Grid.Row="1" />
</Grid>

ด้วยการเพิ่มแอตทริบิวต์ "Grid.Row = .. " ในการควบคุมลูกของกริดซึ่งจะกำหนดให้กับแถวของตาราง จากนั้นตารางจะปรับขนาดเป็นชายด์ตามที่กำหนดโดยคำจำกัดความของแถว


ไปในทิศทางที่ถูกต้องขอบคุณ ฉันจัดการแทรก Grid ได้แล้ว แต่ตอนนี้ต้องบอก TabControl ว่าควรใช้ขนาดทั้งหมดที่ยังมีอยู่ไหม ฉันจะบรรลุสิ่งนั้นได้อย่างไร?
citronas

คุณต้องเพิ่มแอตทริบิวต์ "Grid.Row" สำหรับ TabControl และกำหนดความสูงของแถวที่เกี่ยวข้องเป็น "*" ตามที่แสดงในตัวอย่าง
andyp

0

ฉันลองหลายวิธีที่นี่ แต่ไม่สามารถแก้ปัญหาของฉันได้ (เติมการควบคุมอื่น ๆ ในการควบคุม)

จนกว่าฉันจะพบมัน

<Name_Control Height="auto" Width="auto"/>
//default
//HorizontalAlignment="Stretch" 
//VerticalAlignment="Stretch"

ตัวอย่าง:

//UserControl:
<UserControl Name="UC_Test" Height="auto" Width="auto" />
//Grid: 
<Grid Name="Grid_test" Grid.ColumnSpan="2" Grid.Row="2" />
//Code: 
Grid_test.Children.Add(UC_Test);

เพื่อการออกแบบที่ง่าย

<UserControl Name="UC_Test" Height="100" Width="100" />
//Code
Grid_test.Children.Add(UC_Test);
UC_Test.Width = Double.NaN;
UC_Test.Height = Double.NaN;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.