how to set the width of a column in a datagrid with a multivalue converter?

ComptonAlvaro 166 Reputation points
2022-04-06T12:03:40.46+00:00

I would like to set the width of a column in a datagrid according to some conditions, so I wanted to use a multivalue converter.

I am trying this:

<DataGridTextColumn 
                                                Binding="{Binding Modelo}"
                                                Width="*"
                                                CellStyle="{StaticResource ResourceKey=DataGridCellLeftHorizontalAlignment}">

                                <DataGridTextColumn.ElementStyle>
                                    <Style TargetType="{x:Type TextBlock}">
                                        <!--Se pone en blanco por defecto, de este modo si hay líneas de descuento de factura,
                                        no tendrá artículo, es lo correcto.-->
                                        <Setter Property="Width" Value="10"/>
                                        <Setter Property="Width">
                                            <Setter.Value>
                                                <MultiBinding Converter="{StaticResource docListadosDocumentosDataGridComponentesColumnWidthMultiValueConverter}">
                                                    <MultiBinding.Bindings>
                                                        <Binding />
                                                        <Binding ElementName="cmbTiposContenidos" Path="SelectedItem"/>
                                                    </MultiBinding.Bindings>
                                                </MultiBinding>
                                            </Setter.Value>
                                        </Setter>
                                    </Style>
                                </DataGridTextColumn.ElementStyle>

But i don't am not able to set the width with the value that the multivalueconverter returns. The converter, for testing, returns always 500.

How could I set the width of the column with a multivalue converter?

Thanks.

Developer technologies Windows Presentation Foundation
Developer technologies XAML
0 comments No comments
{count} votes

Accepted answer
  1. Hui Liu-MSFT 48,676 Reputation points Microsoft External Staff
    2022-04-07T08:54:22.083+00:00

    MainWindow.xaml:

    <Window.Resources>  
            <local:ViewModel x:Key="vm"/>  
            <local:MyMultiValueConverter x:Key="MyMultiValueConverter"/>  
        </Window.Resources>  
        <StackPanel DataContext="{StaticResource vm}">  
            <DataGrid Name="dg" ItemsSource="{Binding View}" AutoGenerateColumns="False">  
                <DataGrid.Columns>  
                    <DataGridTextColumn Header="Col1"  Binding="{Binding SomeString}"  MinWidth="30" MaxWidth="300"  >  
                        <DataGridTextColumn.Width>  
                            <MultiBinding Converter="{StaticResource MyMultiValueConverter}">  
                                <Binding Path="WidthValue" Source="{StaticResource vm}"/>  
                                <Binding Path="WidthDefault" Source="{StaticResource vm}"/>  
                            </MultiBinding>  
                        </DataGridTextColumn.Width>  
                        <DataGridTextColumn.ElementStyle>  
                            <Style TargetType="{x:Type TextBlock}">  
                                <Setter Property="TextAlignment" Value="Center"/>  
                                <Setter Property="Width">  
                                    <Setter.Value>  
                                        <MultiBinding Converter="{StaticResource MyMultiValueConverter}">  
                                            <Binding Path="WidthValue" Source="{StaticResource vm}"/>  
                                            <Binding Path="WidthDefault" Source="{StaticResource vm}"/>  
                                        </MultiBinding>  
                                    </Setter.Value>  
                                </Setter>  
                            </Style>  
                        </DataGridTextColumn.ElementStyle>  
                    </DataGridTextColumn>  
                </DataGrid.Columns>  
            </DataGrid>  
            <CheckBox IsChecked="{Binding WidthDefault}" Content="Default Width"/>  
            <Slider Width="200" Height="20" Minimum="5"  Maximum="300" Value="{Binding WidthValue}"/>  
            <!--<TextBox Text="{Binding WidthValue}"/>-->  
        </StackPanel>  
    

    MainWindow.xaml.cs:

    public class ViewModel : INotifyPropertyChanged  
      {  
        public ViewModel()  
        {  
          ObservableCollection<Data> col = new ObservableCollection<Data>();  
           col.Add(new Data() { SomeString = 44 });  
           col.Add(new Data() { SomeString = 84 });  
           col.Add(new Data() { SomeString = 104 });  
          cvs.Source = col;  
        }  
        private CollectionViewSource cvs = new CollectionViewSource();  
        public ICollectionView View { get => cvs.View; }  
      
        private double _widthValue = 30;  
        public double WidthValue  
        {  
          get => this._widthValue;  
          set { this._widthValue = value; OnPorpertyChanged(); }  
        }  
      
        private bool _widthDefault = false;  
        public bool WidthDefault  
        {  
          get => this._widthDefault;  
          set { this._widthDefault = value; OnPorpertyChanged(); }  
        }  
      
        public event PropertyChangedEventHandler PropertyChanged;  
        internal void OnPorpertyChanged([CallerMemberName] string propName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));  
      
      }  
      
      public class Data  
      {  
        public double SomeString { get; set; }  
      }  
      
      public class MyMultiValueConverter : IMultiValueConverter  
      {  
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)  
        {  
          double w =30;  
          if (!(bool)values[1]) double.TryParse(values[0].ToString(), out w);  
          return w;  
        }  
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)  
        {  
          throw new NotImplementedException();  
        }  
      }  
    

    The result:

    190837-5.png


    If the response is helpful, please click "Accept Answer" and upvote it.
     Note: Please follow the steps in our [documentation][5] to enable e-mail notifications if you want to receive the related email notification for this thread. 

    1 person found this answer helpful.

1 additional answer

Sort by: Most helpful
  1. ComptonAlvaro 166 Reputation points
    2022-04-07T17:41:19.7+00:00

    The solution it is to use 2 converters, one for the width of the column and the other for the width of the textblock, because for the column it is needed to use a DataGridLength:

    The solution would be this:

    The view model:

    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Windows.Data;
    using System.Runtime.CompilerServices;
    using System.Globalization;
    using System.Windows.Controls;
    
    namespace ModificarColumnaDataGridConMultivalueConverter
    {
        public class ViewModel : INotifyPropertyChanged
        {
            public ViewModel()
            {
                ObservableCollection<Data> col = new ObservableCollection<Data>();
                col.Add(new Data() { SomeString = 44 });
                col.Add(new Data() { SomeString = 84 });
                col.Add(new Data() { SomeString = 104 });
                cvs.Source = col;
            }
            private CollectionViewSource cvs = new CollectionViewSource();
            public ICollectionView View { get => cvs.View; }
    
            private double _widthValue = 30;
            public double WidthValue
            {
                get => this._widthValue;
                set { this._widthValue = value; OnPorpertyChanged(); }
            }
    
            private bool _widthDefault = false;
            public bool WidthDefault
            {
                get => this._widthDefault;
                set { this._widthDefault = value; OnPorpertyChanged(); }
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
            internal void OnPorpertyChanged([CallerMemberName] string propName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        }
    
    
        public class Data
        {
            public double SomeString { get; set; }
        }
    
        public class MyColumnWidthConverter : IMultiValueConverter
        {
            public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
            {
                double w = 30;
                if (!(bool)values[1]) double.TryParse(values[0].ToString(), out w);
                return new DataGridLength(w);
            }
            public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }
    
        public class MyTexBlockWidthConverter : IMultiValueConverter
        {
            public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
            {
                double w = 30;
                if (!(bool)values[1]) double.TryParse(values[0].ToString(), out w);
                return w;
            }
            public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }
    

    And the view:

    <Window x:Class="ModificarColumnaDataGridConMultivalueConverter.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:ModificarColumnaDataGridConMultivalueConverter"
            mc:Ignorable="d"
            Title="MainWindow" Height="450" Width="800">
    
    
        <Window.Resources>
            <local:ViewModel x:Key="vm"/>
            <local:MyColumnWidthConverter x:Key="MyColumnWidthConverter"/>
            <local:MyTexBlockWidthConverter x:Key="MyTexBlockWidthConverter"/>
        </Window.Resources>
        <StackPanel DataContext="{StaticResource vm}">
            <DataGrid Name="dg" ItemsSource="{Binding View}" AutoGenerateColumns="False">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Col1"  Binding="{Binding SomeString}"  MinWidth="0" MaxWidth="300"  >
                        <DataGridTextColumn.Width>
                            <MultiBinding Converter="{StaticResource MyColumnWidthConverter}">
                                <Binding Path="WidthValue" Source="{StaticResource vm}"/>
                                <Binding Path="WidthDefault" Source="{StaticResource vm}"/>
                            </MultiBinding>
                        </DataGridTextColumn.Width>
                        <DataGridTextColumn.ElementStyle>
                            <Style TargetType="{x:Type TextBlock}">
                                <Setter Property="TextAlignment" Value="Center"/>
                                <Setter Property="Width">
                                    <Setter.Value>
                                        <MultiBinding Converter="{StaticResource MyTexBlockWidthConverter}">
                                            <Binding Path="WidthValue" Source="{StaticResource vm}"/>
                                            <Binding Path="WidthDefault" Source="{StaticResource vm}"/>
                                        </MultiBinding>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </DataGridTextColumn.ElementStyle>
                    </DataGridTextColumn>
                </DataGrid.Columns>
            </DataGrid>
            <CheckBox IsChecked="{Binding WidthDefault}" Content="Default Width"/>
            <Slider Width="200" Height="20" Minimum="5"  Maximum="300" Value="{Binding WidthValue}"/>
            <!--<TextBox Text="{Binding WidthValue}"/>-->
        </StackPanel>
    </Window>
    
    1 person found this answer helpful.
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.