Different specification of WPF grid row sizes of the same user control depending of situation

98 views Asked by At

I have done reusable user control which is used few times in my project.

Usually the second row of the main grid needs to be 7 times bigger than first one, but in a particular situation it needs to be just 5 times bigger.

<Grid x:Name="mainGrid">    
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="7*"/>
    </Grid.RowDefinitions>
    ...
</Grid>

I tried to set it through XAML:

<helperControls:AttachmentsGridControl x:Name="projectAttachmentsControl" ... HeightOfSecondRow="5" />

and in .cs part:

public int HeightOfSecondRow { get; set; }
public AttachmentsGridControl()
{
    InitializeComponent();
    if(HeightOfSecondRow > 0)
        this.mainGrid.RowDefinitions[1].Height = new GridLength(HeightOfSecondRow, GridUnitType.Star);
}

But the value is not passed while constructors of controls are called. The value needs to be passed on a time when constructor is called, so I can specify how much the height of the second row needs to be and render it properly.

1

There are 1 answers

3
thatguy On BEST ANSWER

Instead of overwriting the HeightOfSecondRow in the constructor, make it a dependency property of type GridLength with a default value of 7*. The coerce value callback will ensure that a value that is set in XAML or bound with a binding will be positive, otherwise it will be replaced with the default value.

public partial class AttachmentsGridControl : UserControl
{
   public static readonly DependencyProperty HeightOfSecondRowProperty = DependencyProperty.Register(
      nameof(HeightOfSecondRow), typeof(GridLength), typeof(AttachmentsGridControl),
      new PropertyMetadata(new GridLength(7, GridUnitType.Star), null, OnCoerceValue));

   public GridLength HeightOfSecondRow
   {
      get => (GridLength)GetValue(HeightOfSecondRowProperty);
      set => SetValue(HeightOfSecondRowProperty, value);
   }

   public AttachmentsGridControl()
   {
      InitializeComponent();
   }

   private static object OnCoerceValue(DependencyObject d, object value)
   {
      var gridLength = (GridLength)value;
      return gridLength.Value > 0.0 ? gridLength : HeightOfSecondRowProperty.GetMetadata(d).DefaultValue;
   }
}

Adapt the binding of Height to use the HeightOfSecondRow property of your AttachmentsGridControl.

<Grid x:Name="mainGrid">
   <Grid.RowDefinitions>
      <RowDefinition Height="*"/>
      <RowDefinition Height="{Binding HeightOfSecondRow, RelativeSource={RelativeSource AncestorType={x:Type local:AttachmentsGridControl}}}"/>
   </Grid.RowDefinitions>
   <!-- ...your content. -->
</Grid>

Then you can set the HeightOfSecondRow as before. If you do not set it, the default value will be used.

<local:AttachmentsGridControl x:Name="projectAttachmentsControl" HeightOfSecondRow="20*"/>