0

i have 3 columns, while using a specific converter i succeed to change visibility of the middle and right column to visibility collapse or visible.

My problem is that when those columns should be visible, i want them be have a width in stars, when collapse width must be as auto.

Then if their visibility is visible, all my columns are sharing equivalent spaces, otherwise she will take all the space and can be centered into the parent.

I set my visiblity converter

internal class TradeUnitLevelToVisibilityConverter : BaseConverter, IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value != null && (TradeUnit)value == TradeUnit.Unit
            ? Visibility.Collapsed
            : Visibility.Visible;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return null;
    }
}

my width converter

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value != null && (TradeUnit)value == TradeUnit.Unit
            ? new GridLength(0, GridUnitType.Auto)
            : new GridLength(5, GridUnitType.Star);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return null;
    }
}

my xaml :

       <Grid Grid.Column="1" Background="{StaticResource Black3C3D41Brush}">
            <Grid Grid.Column="1" HorizontalAlignment="Stretch">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="0.5*"/>
                    <ColumnDefinition Width="2.5*"/>
                    <ColumnDefinition >
                        <!--<ColumnDefinition.Style>
                            <Style TargetType="ColumnDefinition">
                                <Setter Property="Width" Value="*"/>
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding , Converter={eshopeur:TradeUnitLevelToVisibilityConverter}}" Value="Unit">
                                        <Setter Property="Width" Value="auto"/>
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </ColumnDefinition.Style>-->
                    </ColumnDefinition>
                    <ColumnDefinition >
                        <!--<ColumnDefinition.Style>
                            <Style TargetType="ColumnDefinition">
                                <Setter Property="Width" Value="2.5*"/>
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding , Converter={eshopeur:TradeUnitLevelToVisibilityConverter}}" Value="Collapsed">
                                        <Setter Property="Width" Value="auto"/>
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </ColumnDefinition.Style>-->
                    </ColumnDefinition>
                    <ColumnDefinition Width="0.5*"/>
                </Grid.ColumnDefinitions>

                <Grid Grid.Column="1" HorizontalAlignment="Center">
                    
                    ...
                    
                </Grid>
                <Grid Grid.Column="2"  Visibility="{Binding UnitTradeUnitlevel, 
                        Converter={eshopeur:TradeUnitLevelToVisibilityConverter}}"  
                      HorizontalAlignment="Stretch"
                      Width="{Binding UnitTradeUnitlevel, Converter={auxilaryscreen:UnitTradeUnitToVisibilityConverter}}" >

                    <Grid>
                        ...
                </Grid>
                <Grid Grid.Column="3"  HorizontalAlignment="Stretch" 
                      Width="{Binding UnitTradeUnitlevel, Converter={auxilaryscreen:UnitTradeUnitToVisibilityConverter}}" 
                      Visibility="{Binding UnitTradeUnitlevel, Converter={eshopeur:TradeUnitLevelToVisibilityConverter}}">
                    
                     ...
                   
                </Grid>
            </Grid>
        </Grid>

i tried with trigger but i don't know how to set them properly as they are checking the visibility converter to adapt the width.

here is what i expect while all visible

all visible

when collapse

collapse

my actual result is for collapse :

today collapse result

do you have any solution to change at the same time the column visibility and width ?

3
  • What about using Visibility.Hidden instead of Visibility.Collapsed?
    – devsmn
    Commented Aug 21, 2020 at 13:19
  • .Hidden will also keep the column space. the visibility.Collapse wil properly ignore the spaces if i succeed to set the width of the column to auto instead of * when the visibility is collapse. Commented Aug 21, 2020 at 13:26
  • You can try to use jagged arrays layout: instead of table-like top container with rows and columns define a list or rows, where each row is another container for cells. This will give you more flexibility (e.g. you will be able to occupy all available width by collapsing cells), but now you will have another problem: how to synchronize cells width between rows.
    – Sinatr
    Commented Aug 21, 2020 at 13:39

2 Answers 2

0

One way to achieve your result is to create an attached behavior for your column definitions.

The attached behavior is a static class with 3 attached properties. You can change the names to actually make sense.

  • DefaultWidth - the default width of the column definition
  • UnitWidth - the width of the column definition when the TradeUnit is Unit
  • TradeUnit - the trade unit

When TradeUnit changes the behavior will set the column definition's Width to the proper value DefaultWidth or UnitWidth.

using System.Windows;
using System.Windows.Controls;

namespace SO
{
    public static class TradeUnitColumnWidthBehavior
    {
        #region DefaultWidth (Attached Property)
        public static readonly DependencyProperty DefaultWidthProperty =
            DependencyProperty.RegisterAttached(
                "DefaultWidth",
                typeof(GridLength),
                typeof(TradeUnitColumnWidthBehavior),
                new PropertyMetadata(null));

        public static GridLength GetDefaultWidth(DependencyObject obj)
        {
            return (GridLength)obj.GetValue(DefaultWidthProperty);
        }

        public static void SetDefaultWidth(DependencyObject obj, GridLength value)
        {
            obj.SetValue(DefaultWidthProperty, value);
        }
        #endregion

        #region UnitWidth (Attached Property)
        public static readonly DependencyProperty UnitWidthProperty =
            DependencyProperty.RegisterAttached(
                "UnitWidth",
                typeof(GridLength),
                typeof(TradeUnitColumnWidthBehavior),
                new PropertyMetadata(null));

        public static GridLength GetUnitWidth(DependencyObject obj)
        {
            return (GridLength)obj.GetValue(UnitWidthProperty);
        }

        public static void SetUnitWidth(DependencyObject obj, GridLength value)
        {
            obj.SetValue(UnitWidthProperty, value);
        }
        #endregion

        #region TradeUnit (Attached Property)
        public static readonly DependencyProperty TradeUnitProperty =
            DependencyProperty.RegisterAttached(
                "TradeUnit",
                typeof(MainWindowViewModel.TradeUnit),
                typeof(TradeUnitColumnWidthBehavior),
                new PropertyMetadata(MainWindowViewModel.TradeUnit.None, OnTradeUnitChanged));

        public static MainWindowViewModel.TradeUnit GetTradeUnit(DependencyObject obj)
        {
            return (MainWindowViewModel.TradeUnit)obj.GetValue(TradeUnitProperty);
        }

        public static void SetTradeUnit(DependencyObject obj, MainWindowViewModel.TradeUnit value)
        {
            obj.SetValue(TradeUnitProperty, value);
        }

        private static void OnTradeUnitChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var columnDefinition = (ColumnDefinition)d;
            if (columnDefinition == null) return;

            if ((MainWindowViewModel.TradeUnit) e.NewValue == MainWindowViewModel.TradeUnit.Unit)
            {
                columnDefinition.Width = GetUnitWidth(d);
            }
            else
            {
                columnDefinition.Width = GetDefaultWidth(d);
            }
        }
        #endregion
    }
}

Here is an example of the XAML:

<Grid ShowGridLines="True">
    <!--    -->
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="0.5*" />
        <ColumnDefinition Width="2.5*" 
            local:TradeUnitColumnWidthBehavior.DefaultWidth="2.5*" 
            local:TradeUnitColumnWidthBehavior.TradeUnit="{Binding RelativeSource={RelativeSource AncestorType={x:Type Grid}}, Path=DataContext.UnitTradeUnitLevel}" 
            local:TradeUnitColumnWidthBehavior.UnitWidth="*" />
        <ColumnDefinition Width="1.5*" 
            local:TradeUnitColumnWidthBehavior.DefaultWidth="1.5*" 
            local:TradeUnitColumnWidthBehavior.TradeUnit="{Binding RelativeSource={RelativeSource AncestorType={x:Type Grid}}, Path=DataContext.UnitTradeUnitLevel}" 
            local:TradeUnitColumnWidthBehavior.UnitWidth="Auto" />
        <ColumnDefinition Width="2.5*" 
            local:TradeUnitColumnWidthBehavior.DefaultWidth="2.5*" 
            local:TradeUnitColumnWidthBehavior.TradeUnit="{Binding RelativeSource={RelativeSource AncestorType={x:Type Grid}}, Path=DataContext.UnitTradeUnitLevel}" 
            local:TradeUnitColumnWidthBehavior.UnitWidth="Auto" />
        <ColumnDefinition Width="0.5*" />
    </Grid.ColumnDefinitions>
    <Border x:Name="Border1"
        Grid.Column="1"
        Background="Red">
        <Button
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Command="{Binding TradeUnitCommand}"
            Content="Change Unit" />
    </Border>
    <Border
        Grid.Column="2"
        Background="Green"
        Visibility="{Binding UnitTradeUnitLevel, Converter={StaticResource TradeUnitLevelToVisibilityConverter}}" />
    <Border
        Grid.Column="3"
        Background="Blue"
        Visibility="{Binding UnitTradeUnitLevel, Converter={StaticResource TradeUnitLevelToVisibilityConverter}}" />
</Grid>
0

finally I changed my xaml tree and and a converter : when a column is visible, the other one is not, all set as width = auto.

it seems to do the job, when if i can find a cleaner solution it would be nice. if someone already did it with trigger i am interested in.

Not the answer you're looking for? Browse other questions tagged or ask your own question.