oillio
oillio

Reputation: 4908

Creating complex calculations for Grid column width in WPF

Is it possible to create complex calculations for determining the widths of columns (or any control) in WPF? So, for instance, I want Grid.Column3.Width to equal Grid.Width - Grid.Column2.Width - 100.

Specifically, this is what I am working on:

I have a grid with three columns. The first column has a cancel button who may be collapsed. The second has a text box. And the third has a Progress Bar (that may be collapsed).

I want the button always have all the width it needs (if it is visible). I would like try to show all of the text box. And give all of the rest of the width to the progress bar (if it is visible). But I don't want the progress bar to be less than 200. The text box should be truncated if necessary to give the progress bar a minimum of 200.

So, I want something like this:

 <Grid.ColumnDefinitions>
  <ColumnDefinition Width="Auto"/>
  <ColumnDefinition Width="Auto"/>
  <ColumnDefinition Width="*" MinWidth="200"/>   
 </Grid.ColumnDefinitions>

But that doesn't work (The progress bar will be pushed off of the side of the grid if there is not enough room).

What is the best way to represent this? Can I do it entirely in XAML, or am I going to need to use code-behind?

Upvotes: 1

Views: 1104

Answers (1)

Fredrik Hedblad
Fredrik Hedblad

Reputation: 84647

I can't come up with a way to do this strictly in Xaml.
You could use a MultiBinding for the MaxWidth of the TextBox where you use the following as Bindings

  • ActualWidth of Grid
  • ActualWidth of Button
  • MinWidth of ProgressBar

Xaml

<Grid Name="grid">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Button Name="button" Grid.Column="0" Content="Cancel"/>
    <TextBox Grid.Column="1" Text="Some Text">
        <TextBox.MaxWidth>
            <MultiBinding Converter="{StaticResource MaxWidthMultiConverter}">
                <Binding ElementName="grid" Path="ActualWidth"/>
                <Binding ElementName="button" Path="ActualWidth"/>
                <Binding ElementName="progressBar" Path="MinWidth"/>
            </MultiBinding>
        </TextBox.MaxWidth>
    </TextBox>
    <ProgressBar Name="progressBar" Grid.Column="2" Value="50" Maximum="100" MinWidth="200"/>
</Grid>

MaxWidthMultiConverter

public class MaxWidthMultiConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        double gridWidth = (double)values[0];
        double buttonWidth = (double)values[1];
        double progressBarMaxWidth = (double)values[2];
        return gridWidth - (buttonWidth + progressBarMaxWidth);
    }
    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Upvotes: 3

Related Questions