Pass the value of one control to a Converter to set the width on another control Pass the value of one control to a Converter to set the width on another control wpf wpf

Pass the value of one control to a Converter to set the width on another control


you're supposed to use the other control as the source, not the parameter.The parameter has to be a constant and in your case can be -5.

I'm not near VS at the moment so the syntax maybe inaccurate, however, it is something like:

Width="{Binding ElementName=LayoutRoot, Path=ActualWidth,Converter={StaticResource PositionConverter}, ConverterParameter=-5}"

(The converter will receive -5 as a string and will have to convert it into a number before using it.)

From my experience it is better to use the OnXXXChanged callback of DependecyProperty XXX, and not bind controls within the same window/root control one to another.One of the reasons for this is that you may want to bind them to an external element later on.

Or alternatively, use multibinding:

<TextBlock>    <TextBlock.Width>        <MultiBinding Converter="{StaticResource yourConverter}">            <MultiBinding.Bindings>                <Binding /> <!-- Bind to parameter 1 here -->                <Binding /> <!-- Bind to parameter 2 here -->          </MultiBinding.Bindings>        </MultiBinding>    </TextBlock.Width></TextBlock>

and and a converter which converts the two parameters to the value you want.


yes..multi binding works for me.. actually i tried to send a element as a convereterparameter, but its not accepting. thats why i passed the element as a value to the converter class.

below is my example..

<ListView ... ><ListView.View><GridView>    <GridViewColumn Header="xyz" >        <GridViewColumn.Width>            <MultiBinding Converter="{StaticResource GetWidthfromParentControl}">                <MultiBinding.Bindings>                    <Binding ElementName="lstNetwork" Path="ActualWidth"/>                    <Binding ElementName="MyGridView"/>                </MultiBinding.Bindings>            </MultiBinding>        </GridViewColumn.Width>    ....    </GridViewColumn>    <GridViewColumn ...>    ....    </GridViewColumn></GridView></ListView.View></ListView>

In window resize, my first gridviewcolumn has to be resized, not the other two gridviewcolumns..i passed Actualwidth of listview and also total gridview object as an element.. if you go the converter code...

class GetWidthfromParentControl : IMultiValueConverter{    #region IMultiValueConverter Members    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)    {        GridView view = values[1] as GridView;        GridViewColumnCollection collc = view.Columns;        double actualWidths = collc[1].ActualWidth + collc[2].ActualWidth;        return ((double)values[0] - actualWidths );    }    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)    {        return null;    }    #endregion}

this worked for me... :)


Although I suspect there may be a better way to solve your problem, I think I have an answer for what you want to do. ( You didn't mention what type your container is. A StackPanel for instance takes care of the width calculation for you. See TextBox#2 below)

First the XAML

<Window x:Class="WpfApplication1.Window2" ...    xmlns:local="clr-namespace:WpfApplication1"    Title="Window2" Height="300" Width="300">    <Window.Resources>        <local:WidthSansMarginConverter x:Key="widthConverter" />    </Window.Resources>    <Grid>        <StackPanel x:Name="stack">            <TextBlock x:Name="txtStatusMessages"                     Width="{Binding ElementName=stack,Path=ActualWidth,                         Converter={StaticResource widthConverter}}"                    TextWrapping="WrapWithOverflow"                     Background="Aquamarine"                     Margin="5,5,5,5">                This is a message            </TextBlock>            <TextBlock x:Name="txtWhatsWrongWithThis"                     TextWrapping="WrapWithOverflow"                     Background="Aquamarine"                     Margin="5,5,5,5">                This is another message            </TextBlock>        </StackPanel>    </Grid></Window>

Next the Converter. We have a problem here.. since the ConverterParameter for the Convert methods cannot be a dynamic value for some reason. So we sneak in the Textbox Margin via a public property of the Converter that we set in Window's ctor.WidthSansMarginConverter.cs

public class WidthSansMarginConverter : IValueConverter    {        private Thickness m_Margin = new Thickness(0.0);        public Thickness Margin        {            get { return m_Margin; }            set { m_Margin = value; }        }        #region IValueConverter Members        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)        {            if (targetType != typeof(double)) { return null; }            double dParentWidth = Double.Parse(value.ToString());            double dAdjustedWidth = dParentWidth-m_Margin.Left-m_Margin.Right;            return (dAdjustedWidth < 0 ? 0 : dAdjustedWidth);        }        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)        {            throw new NotImplementedException();        }        #endregion    }

Window2.xaml.cs

        public Window2()        {            InitializeComponent();            WidthSansMarginConverter obConverter = this.FindResource("widthConverter") as WidthSansMarginConverter;            obConverter.Margin = txtStatusMessages.Margin;        }

HTH. Thanks for the exercise :)