ซ่อนแถวตารางใน WPF


97

ฉันมีแบบฟอร์ม WPF ง่ายๆพร้อมGridประกาศในแบบฟอร์ม นี้Gridมีพวงของแถว:

<Grid.RowDefinitions>
    <RowDefinition Height="Auto" MinHeight="30" />
    <RowDefinition Height="Auto" Name="rowToHide" />
    <RowDefinition Height="Auto" MinHeight="30" />
</Grid.RowDefinitions>

แถวชื่อrowToHideมีช่องป้อนข้อมูลไม่กี่ช่องและฉันต้องการซ่อนแถวนี้หลังจากตรวจพบว่าไม่ต้องการช่องเหล่านี้ ง่ายพอที่จะตั้งค่าVisibility = Hiddenเป็นรายการทั้งหมดในแถว แต่แถวยังคงใช้พื้นที่ในไฟล์Grid. ฉันพยายามตั้งค่าHeight = 0รายการ แต่ดูเหมือนจะไม่ได้ผล

คุณสามารถคิดได้ดังนี้คุณมีแบบฟอร์มในนั้นคุณมีเมนูแบบเลื่อนลงว่า "ประเภทการชำระเงิน" และหากบุคคลนั้นเลือก "เงินสด" คุณต้องการซ่อนแถวที่มีรายละเอียดบัตร ไม่ใช่ตัวเลือกในการเริ่มแบบฟอร์มด้วยสิ่งนี้ที่ซ่อนอยู่แล้ว


1
ดูเคล็ดลับเกี่ยวกับการมองเห็นเป็นระบบ 3 สถานะ (ในเธรดเคล็ดลับ WPF): stackoverflow.com/questions/860193/wpf-simple-tips-and-tricks/…
Metro Smurf

สิ่งที่ยอดเยี่ยม ... หากคุณใส่มันลงไปเป็นคำตอบฉันจะทำเครื่องหมายว่า ...
Richard

ดูเคล็ดลับนี้เช่นกัน: social.msdn.microsoft.com/Forums/en-US/wpf/thread/…
Domokun

คำตอบ:


90

แถวไม่มีคุณสมบัติการมองเห็นอย่างที่คนอื่นบอกคุณต้องตั้งค่าความสูง อีกทางเลือกหนึ่งคือการใช้ตัวแปลงในกรณีที่คุณต้องการฟังก์ชันนี้ในหลาย ๆ มุมมอง:

    [ValueConversion(typeof(bool), typeof(GridLength))]
    public class BoolToGridRowHeightConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return ((bool)value == true) ? new GridLength(1, GridUnitType.Star) : new GridLength(0);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {    // Don't need any convert back
            return null;
        }
    }

จากนั้นในมุมมองที่เหมาะสม<Grid.RowDefinition>:

<RowDefinition Height="{Binding IsHiddenRow, Converter={StaticResource BoolToGridRowHeightConverter}}"></RowDefinition>

11
UpVoted - ผู้แปลงอนุญาตให้มีการประกาศทั้งหมดนี้ใน Xaml โดยทั่วไปฉันเกลียดการใช้รหัสลับในการเล่นซอกับภาพ
Allen

1
สิ่งนี้มีประโยชน์และสามารถขยายได้ง่าย ผมขอแนะนำให้เรียกมันBoolToGridLengthConverterและเพิ่มVisibleLength-Property (bool)value == trueเพื่อกลับบน นั่นคือวิธีที่คุณสามารถใช้ซ้ำได้ด้วยAutoและ fix-Value
LuckyLikey

1
คำตอบที่ดี ฉันคิดว่าคุณหมายถึง IsDisplayedRow ไม่ใช่ IsHiddenRow
NielW

73

วิธีที่ดีที่สุดและสะอาดในการยุบแถวหรือคอลัมน์คือการใช้ DataTrigger ในกรณีของคุณ:

<Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto" MinHeight="30" />
      <RowDefinition Name="rowToHide">
        <RowDefinition.Style>
          <Style TargetType="{x:Type RowDefinition}">
            <Setter Property="Height" Value="Auto" />
            <Style.Triggers>
              <DataTrigger Binding="{Binding SomeBoolProperty}" Value="True">
                <Setter Property="Height" Value="0" />
              </DataTrigger>
            </Style.Triggers>
          </Style>
        </RowDefinition.Style>
      </RowDefinition>
      <RowDefinition Height="Auto" MinHeight="30" />
    </Grid.RowDefinitions>
  </Grid>

5
ฉันชอบแนวทางนี้เพราะคุณไม่ต้องการรหัส C # เพิ่มเติม
user11909

1
อย่าลืมติดตั้งINotifyPropertyChangedในโค้ดของคุณด้านหลังเพื่อให้ใช้งานได้เมื่อSomeBoolPropertyมีการเปลี่ยนแปลง :)
benichka

55

คุณยังสามารถทำได้โดยอ้างอิงแถวในตารางแล้วเปลี่ยนความสูงของแถวเอง

XAML

<Grid Grid.Column="2" Grid.Row="1" x:Name="Links">
   <Grid.RowDefinitions>
      <RowDefinition Height="60" />
      <RowDefinition Height="*" />
      <RowDefinition Height="*" />
      <RowDefinition Height="80" />
   </Grid.RowDefinitions>
</Grid>

VB.NET

If LinksList.Items.Count > 0 Then
   Links.RowDefinitions(2).Height = New GridLength(1, GridUnitType.Star)
Else
   Links.RowDefinitions(2).Height = New GridLength(0)
End If

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


2
นอกจากนี้ยังมีข้อดีของการทำงานกับแถวที่ใช้สัญลักษณ์รูปดาว!
Johny Skovdal

1
การทำเช่นนี้ในโค้ดเป็นวิธีแก้ปัญหาที่ชัดเจนและอ่านง่ายที่สุด อาจจะเพิ่มความคิดเห็นหลังRowDefinitionเช่น<RowDefinition Height="*" /><!-- Height set in code behind -->
Kay Zed

2
ฉันไม่คิดว่านี่เป็นวิธีแก้ปัญหาที่ชัดเจนและอ่านง่ายที่สุดเนื่องจากรหัสการทำงานแบ่งออกเป็นสองไฟล์ที่แยกจากกัน ในความเป็นจริงมันสามารถทำได้ด้วย XAML บริสุทธิ์ - ดูคำตอบของฉัน
Lukáš Koten

ความต้องการของฉันแตกต่างกันเล็กน้อยและอยู่ใน C # แต่ตัวอย่างนี้ชี้ให้ฉันไปในทิศทางที่ถูกต้อง ขอบคุณ!
nrod

30

สำหรับการอ้างอิงVisibilityคือSystem.Windows.Visibility enumeration สามสถานะ:

  • มองเห็นได้ - องค์ประกอบได้รับการแสดงผลและมีส่วนร่วมในเค้าโครง
  • ยุบ - องค์ประกอบจะมองไม่เห็นและไม่มีส่วนร่วมในเค้าโครง ให้ความสูงและความกว้างเป็น 0 อย่างมีประสิทธิภาพและทำงานราวกับว่าไม่มีอยู่จริง
  • ซ่อน - องค์ประกอบจะมองไม่เห็น แต่ยังคงมีส่วนร่วมในการจัดวาง

ดูเคล็ดลับนี้และเคล็ดลับอื่น ๆ ในเธรดWPF Tips and Tricks


1
การตั้งค่ารายการทั้งหมดในแถวเป็นการมองเห็นการพับใช้งานได้ขอบคุณ
Richard

1
ฉันลดลงเพราะฉันคิดว่าคำตอบของ @ TravisPUK มีวิธีแก้ปัญหาที่ชัดเจนและชัดเจนกว่า
testpattern

12
@testpattern - โดยทั่วไปจะใช้ downvotes สำหรับคำตอบที่ไม่ถูกต้อง หากคำตอบอื่นดีกว่าให้โหวตคะแนน
Metro Smurf

7
@MetroSmurf พอใช้. อาจเป็นไปได้ว่าคำตอบของคุณไม่ถูกต้องเนื่องจาก RowDefinition ไม่มีคุณสมบัติสำหรับการมองเห็น TravisPUK แสดงวิธีซ่อนแถวและนั่นควรเป็นคำตอบที่ยอมรับได้
testpattern

9

แทนที่จะเล่นซอกับ Grid Row คุณสามารถตั้งค่าคุณสมบัติ Visibility ของ Controls (ช่องในแถว) เป็น "Collapsed" เพื่อให้แน่ใจว่าการควบคุมจะไม่ใช้พื้นที่ใด ๆ และหากคุณมี Grid Row Height = "Auto" แถวนั้นจะถูกซ่อนเนื่องจากตัวควบคุมทั้งหมดในแถวมี Visibility = "Collapsed"

<Grid>
       <Grid.RowDefinitions>
         <RowDefinition Height="Auto" />
         <RowDefinition Height="Auto" Name="rowToHide" />
       </Grid.RowDefinitions>

   <Button Grid.Row=0 Content="Click Me" Height="20">
       <TextBlock Grid.Row=1 
Visibility="{Binding Converter={StaticResource customVisibilityConverter}}" Name="controlToHide"/>

</Grid>

วิธีนี้ดีกว่าเนื่องจากการมองเห็นของตัวควบคุมสามารถผูกไว้กับคุณสมบัติบางอย่างด้วยความช่วยเหลือของตัวแปลง


7

เพียงทำสิ่งนี้:
rowToHide.Height = new GridLength(0);

ถ้าคุณจะใช้visibility.Collapseคุณต้องตั้งค่าสำหรับสมาชิกทุกคนในแถว


6

ตั้งค่าการเปิดเผยเนื้อหาของแถวเป็นVisibility.Collapsedแทนที่จะซ่อน สิ่งนี้จะทำให้เนื้อหาหยุดกินพื้นที่และแถวจะหดอย่างเหมาะสม


1
ฉันเคยเห็นที่อื่นมีคนพูดถึง Row Visibility แต่ Row ไม่มีสถานะการมองเห็น? การตั้งค่ารายการทั้งหมดในแถวเป็นการมองเห็นการพับใช้งานได้แม้ว่า
Richard

5
@Richard: คุณไม่สามารถตั้งค่า RowDefinition.Visibility ได้เนื่องจากไม่ใช่ UIElement แต่คุณสามารถใส่เนื้อหาทั้งหมดสำหรับแถว (หรือแต่ละคอลัมน์ภายในแถว) ลงในคอนเทนเนอร์เดียวและตั้งค่าการแสดงผลของคอนเทนเนอร์นั้นได้
Reed Copsey

1
จะเกิดอะไรขึ้นถ้าแถวกริดของคุณไม่มีเนื้อหาใด ๆ แต่มีความสูงคงที่? มีวิธีที่สะดวกในการแสดง / ซ่อนหรือไม่?
kevinarpe

4

ฉันมีความคิดที่คล้ายกันโดยการสืบทอด RowDefinition (เพียงเพื่อความสนใจ)

public class MyRowDefinition : RowDefinition
{
    private GridLength _height;

    public bool IsHidden
    {
        get { return (bool)GetValue(IsHiddenProperty); }
        set { SetValue(IsHiddenProperty, value); }
    }

    // Using a DependencyProperty as the backing store for IsHidden.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty IsHiddenProperty =
        DependencyProperty.Register("IsHidden", typeof(bool), typeof(MyRowDefinition), new PropertyMetadata(false, Changed));

    public static void Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var o = d as MyRowDefinition;
        o.Toggle((bool)e.NewValue);
    }

    public void Toggle(bool isHidden)
    {
        if (isHidden)
        {
            _height = this.Height;
            this.Height = new GridLength(0, GridUnitType.Star);
        }                                                     
        else
            this.Height = _height;
    }          
}

ตอนนี้คุณสามารถใช้งานได้ดังต่อไปนี้:

 <Grid.RowDefinitions>
        <RowDefinition Height="2*" />
        <my:MyRowDefinition Height="4*" IsHidden="false" x:Name="RowToHide" />
        <RowDefinition Height="*" />
        <RowDefinition Height="60" />
    </Grid.RowDefinitions>

และสลับกับ

RowToHide.IsHidden = !RowToHide.IsHidden;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.