【问题标题】:WPF hide a row, but empty space doesn't sweep outWPF隐藏一行,但空白不扫出
【发布时间】:2017-10-14 07:40:04
【问题描述】:

我有一个带有网格的 wpf 窗口。我想隐藏行,我使用此代码,如其他 stackoverflow 线程所示:

            buttonsGrid.Visibility = Visibility.Collapsed; or buttonsGrid.Height = 0;
            dayTimePicker.Visibility = Visibility.Collapsed; or dayTimePicker.Height = 0;

将 Visibility 设置为 Collapsed 或 Height 设置为 0 会产生相同的效果,但我希望这些 Rows 占用的空白区域被清除...我希望整个窗口被索引行 0 占用...如何我可以吗?

这是我的窗口:

<Window x:Class="PerformanceVideoRec.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
    xmlns:DTControl="clr-namespace:DayTimePickControl"
    Title="{StaticResource ID_TITLE}" Height="600" Width="900" Loaded="Window_Loaded"> <!--Closing="Window_Closing"> -->

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid Grid.Row="1" x:Name="ControlPart" IsEnabled="False">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="6*"/>
            <ColumnDefinition Width="3*"/>
        </Grid.ColumnDefinitions>
        <Grid Grid.Column="0" x:Name="LeftGrid">
            <Grid.RowDefinitions>
                <RowDefinition Height="55*"/>
                <RowDefinition Height="5*"/>
                <RowDefinition Height="5*"/>
                <RowDefinition Height="20*"/>
            </Grid.RowDefinitions>
            <WindowsFormsHost Grid.Row="0" Margin="5" Background="Gray">
                <wf:PictureBox x:Name="playWindow"></wf:PictureBox>
            </WindowsFormsHost>
            <UniformGrid Grid.Row="1">
                <Button x:Name="btnShowHideControls" Content="Nascondi Controlli" Click="btnShowHideControls_Click"/>
            </UniformGrid>
            <UniformGrid Columns="6" Grid.Row="2" x:Name="buttonsGrid">
                <Button x:Name="btnPause" Margin="5" Width="50" Content="{StaticResource ID_PAUSE}" Click="btnPause_Click"></Button>
                <Button x:Name="btnPlay" Margin="5" Width="50" Content="{StaticResource ID_PLAY}" Click="btnPlay_Click"  Visibility="Collapsed"/>
                <Button x:Name="btnStop" Margin="5" Width="50" Content="{StaticResource ID_STOP}" Click="btnStop_Click"></Button>
                <Button x:Name="btnSlow" Margin="5" Width="50" Content="{StaticResource ID_SLOW}" Click="btnSlow_Click"></Button>
                <TextBox x:Name="tbSpeed" IsEnabled="False" Width="50" Height="25" TextAlignment="Center" VerticalContentAlignment="Center" Text="1X" />
                <Button x:Name="btnFast" Margin="5" Width="50" Content="{StaticResource ID_FAST}" Click="btnFast_Click"></Button>
                <Button x:Name="btnNormal" Margin="5" Width="50" Content="{StaticResource ID_NORMAL}" Click="btnNormal_Click"></Button>
            </UniformGrid>
            <DTControl:DayTimePick x:Name="dayTimePicker" Grid.Row="3" Width="550" Height="100" Grid.RowSpan="2" OnTimeClick="dayTimePicker_OnTimeClick"></DTControl:DayTimePick>
        </Grid>
        <Frame x:Name="PlayBackFrame" Grid.Column="1" Background="AliceBlue" ></Frame>

    </Grid>
</Grid>

【问题讨论】:

  • 当您想要折叠控件时,将高度设置为 0 不是一个好习惯。

标签: c# wpf


【解决方案1】:

MVVM方式:

  • 为要折叠的 UI 部分制作单独的视图模型。我们称之为 PlayViewModel,
  • 为它制作一个DataTemplate,
  • 在视图模型中将其作为属性(例如,我们称之为 Play,不要忘记引发属性更改事件)公开,它是整个视图的 DataContext

  • 您将其显示在您的网格中,并使用 ContentPresenter,ContentPresenter.Content 绑定到 Play 属性

  • 您通过将 Play 属性设置为 null 来隐藏,您通过恢复它来显示它。

您可以免费获得可测试性。

【讨论】:

    【解决方案2】:

    您可以使用Data Binding 并将控件的属性Visibility 绑定到要使用转换器折叠的行内。

    我通常使用 NuGet 包Mvvm Lightdocumentation 在使用数据绑定的同时拥有一些便利。 (在这种情况下RelayCommandRaisePropertyChanged 实现)

    一个非常基本的例子:

    部分视图。在这里您可以注意到按钮的Visibility 属性与ViewModel 的属性IsButton1Visible 之间的绑定。当然boolVisibility 不是同一种类型,所以我必须使用IValueConverter 创建一个映射:

     <Grid>
    
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
    
        <Button Grid.Row="0" Content="1" Visibility="{Binding IsButton1Visible, Converter={StaticResource BooleanToVisibilityConverter}}" />
        <Button Grid.Row="1" Content="2" />
        <Button Grid.Row="2" Content="3" />
        <Button Grid.Row="3" Content="4" />
        <Button Grid.Row="4" Content="Toggle button 1 visibility" Command="{Binding ToggleButton1Visibility}" />
    
    </Grid>
    

    后面代码中窗口的构造函数(也可以通过DataContext属性直接将ViewModel绑定到View中),用于将ViewViewModel关联起来:

    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new MyWindowViewModel();
    }
    

    true 转换为Visibility.Visible 的转换器:

    public class BooleanToVisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            => (bool)value ? Visibility.Visible : Visibility.Collapsed;
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    App.xaml, Application.Resource 部分,用于使View“看到”转换器:

    <Application.Resources>
    
        <local:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
    
    </Application.Resources>
    

    视图模型。这里setset的方法IsButton1VisibleRaisePropertyChanged很重要,因为它通知View属性发生了变化,这样View就可以自己刷新了:

    public class MyWindowViewModel : ViewModelBase
    {
        private bool _isButton1Visibile = true;
        public bool IsButton1Visible
        {
            get => _isButton1Visibile;
            set
            {
                if (_isButton1Visibile == value)
                    return;
    
                _isButton1Visibile = value;
                RaisePropertyChanged(nameof(IsButton1Visible));
            }
        }
    
    
        RelayCommand _toggleButton1Visbility;
        public RelayCommand ToggleButton1Visibility
        {
            get
            {
                return _toggleButton1Visbility ?? (_toggleButton1Visbility = new RelayCommand(
                    () =>
                    {
                        IsButton1Visible = !IsButton1Visible;
                    }));
            }
        }
    }
    

    【讨论】:

      【解决方案3】:
      LeftGrid.RowDefinitions[2].Height = new GridLength(0);
      LeftGrid.RowDefinitions[3].Height = new GridLength(0);
      

      如果你想恢复,那就做这个

         LeftGrid.RowDefinitions[2].Height = new GridLength(5, GridUnitType.Star);
          LeftGrid.RowDefinitions[3].Height = new GridLength(20, GridUnitType.Star);
      

      【讨论】:

      • 如果我这样做,我会丢失原始的高度值(55、5、5 和 20)。我该如何设置?
      • 效果很好,谢谢!但是..如何恢复“5*”和“20*”的原始值?
      • 只需设置高点:new GridLength(55, GridUnitType.Star);新的 GridLength(5, GridUnitType.Star);
      • 对不起,我自己修复:LeftGrid.RowDefinitions[2].Height = new GridLength(5, GridUnitType.Star); LeftGrid.RowDefinitions[3].Height = new GridLength(20, GridUnitType.Star
      • 是否也可以隐藏“PlayBackFrame”?
      猜你喜欢
      • 2013-04-25
      • 2023-02-14
      • 2019-03-12
      • 2018-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-14
      • 2014-11-06
      相关资源
      最近更新 更多