代码之家  ›  专栏  ›  技术社区  ›  Johan Danforth

如何在XAML中根据窗口或屏幕大小设置网格列最大宽度

  •  7
  • Johan Danforth  · 技术社区  · 17 年前

    我在一个窗口中有一个三列网格,第一列有一个网格拆分器。我要将第一列的最大宽度设置为父窗口或页的三分之一 Width (或) ActualWidth )如果可能的话,我更愿意在XAML中这样做。

    这是要在xamlpad(或类似的)中使用的示例xaml,它显示了我正在执行的操作。

    <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition x:Name="Column1" Width="200"/>
                <ColumnDefinition x:Name="Column2" MinWidth="50" />
                <ColumnDefinition x:Name="Column3" Width="{ Binding ElementName=Column1, Path=Width }"/>
                </Grid.ColumnDefinitions>
    
            <Label Grid.Column="0" Background="Green" />
            <GridSplitter Grid.Column="0" Width="5" />
            <Label Grid.Column="1" Background="Yellow" />
            <Label Grid.Column="2" Background="Red" />
        </Grid>
    </Page>
    

    如您所见,右列宽度绑定到第一列的宽度,因此当您使用拆分器滑动左列时,右列的操作相同:) 如果将左列向右滑动,最终它将滑动到页面/窗口的一半,并滑动到窗口的右侧,从而推开第2列和第3列。

    我想通过将列1的maxwidth设置为窗口宽度的三分之一(或类似的设置)来防止这种情况。我可以很容易地在代码隐藏中做到这一点,但如何在“仅XAML”中做到这一点?

    编辑: 大卫·施密特建议使用sharedsizegroup而不是binding,这是一个很好的建议。我的示例代码如下所示:

    <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
            <Grid IsSharedSizeScope="True">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition x:Name="Column1" SharedSizeGroup="ColWidth" Width="40"/>
                    <ColumnDefinition x:Name="Column2" MinWidth="50" Width="*" />
                    <ColumnDefinition x:Name="Column3" SharedSizeGroup="ColWidth"/>
                </Grid.ColumnDefinitions>
                <Label Grid.Column="0" Background="Green" />
                <GridSplitter Grid.Column="0" Width="5" />
                <Label Grid.Column="1" Background="Yellow" />
                <Label Grid.Column="2" Background="Red" />
            </Grid>
    </Page>
    
    2 回复  |  直到 17 年前
        1
  •  7
  •   Christopher Bennage    17 年前

    我认为只使用XAML的方法有些迂回,但这里有一种方法可以做到这一点。

    <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
          xmlns:sys="clr-namespace:System;assembly=mscorlib"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
    
        <!-- This contains our real grid, and a reference grid for binding the layout-->
        <Grid x:Name="Container">
    
          <!-- hidden because it's behind the grid below -->
          <Grid x:Name="LayoutReference">
            <Grid.ColumnDefinitions>
              <ColumnDefinition Width="*"/>
              <ColumnDefinition Width="*"/>
              <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <!-- We need the border, because the column doesn't have an ActualWidth -->
            <Border x:Name="ReferenceBorder" 
                    Background="Black" />
            <Border Background="White" Grid.Column="1" />
            <Border Background="Black" Grid.Column="2" />
          </Grid>
    
          <!-- I made this transparent, so we can see the reference -->
          <Grid Opacity="0.9">
              <Grid.ColumnDefinitions>
                  <ColumnDefinition x:Name="Column1" 
                                    MaxWidth="{Binding ElementName=ReferenceBorder,Path=ActualWidth}"/>
                  <ColumnDefinition x:Name="Column2" 
                                    MinWidth="50"  />
                  <ColumnDefinition x:Name="Column3" 
                                    Width="{ Binding ElementName=Column1, Path=Width }"/>
                  </Grid.ColumnDefinitions>
    
              <Label Grid.Column="0" Background="Green"/>
              <GridSplitter Grid.Column="0" Width="5" />
              <Label Grid.Column="1" Background="Yellow" />
              <Label Grid.Column="2" Background="Red" />
          </Grid>
        </Grid>
    
    </Page>
    
        2
  •  0
  •   Thomas daign    17 年前

    太懒了,不能自己写,但你应该能够使用数学转换器,并绑定到你的父窗口宽度(按名称,或用relativesource祖先搜索)。

    //I know I borrowed this from someone, sorry I forgot to add a comment from whom
    public class ScaledValueConverter : IValueConverter
    {
      public Object Convert(Object value, Type targetType, Object parameter, System.Globalization.CultureInfo culture)
      {
         Double scalingFactor = 0;
         if (parameter != null)
         {
            Double.TryParse((String)(parameter), out scalingFactor);
         }
    
         if (scalingFactor == 0.0d)
         {
            return Double.NaN;
         }
    
         return (Double)value * scalingFactor;
      }
    
      public Object ConvertBack(Object value, Type targetType, Object parameter, System.Globalization.CultureInfo culture)
      {
         throw new Exception("The method or operation is not implemented.");
      }
    }
    
    推荐文章