将一个控件的值传递给转换器以设置另一控件的宽度

发布于 2024-07-09 18:16:44 字数 821 浏览 8 评论 0原文

我想根据其容器的宽度设置 TextBlock 的宽度,减去 TextBlock 上设置的边距。

这是我的代码:

<TextBlock x:Name="txtStatusMessages" 
           Width="{Binding ElementName=LayoutRoot,Path=ActualWidth }"
                   TextWrapping="WrapWithOverflow" 
           Foreground="White" 
           Margin="5,5,5,5">This is a message
</TextBlock>

除了由于左右边距 b 设置为 5 导致 TextBlock 太大 10 个单位之外,效果很好。

好吧,所以我想...让我们使用转换器。 但我不知道如何传递容器控件的 ActualWidth (参见上文:LayoutRoot)。

我知道如何使用转换器,甚至是带有参数的转换器,只是不是像这样的参数... Binding ElementName=LayoutRoot,Path=ActualWidth

例如,我无法完成这项工作:

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

我希望我说得足够清楚,并希望你可以帮忙,因为谷歌今晚对我没有帮助。

I want to set the width of a TextBlock based on the width of its container, minus the margins set on the TextBlock.

Here is my code:

<TextBlock x:Name="txtStatusMessages" 
           Width="{Binding ElementName=LayoutRoot,Path=ActualWidth }"
                   TextWrapping="WrapWithOverflow" 
           Foreground="White" 
           Margin="5,5,5,5">This is a message
</TextBlock>

And that works great except for the fact that the TextBlock is 10 units too big due to the Left and Right Margins bbeing set to 5.

OK, so I thought... Let's use a Converter. But I don't know how to pass the ActualWidth of my container control (SEE ABOVE: LayoutRoot).

I know how to use converters, and even converters with parameters, just not a parameter like... Binding ElementName=LayoutRoot,Path=ActualWidth

For example, I can't make this work:

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

I hope I made this clear enough and hope that you can help because Google is no help for me tonight.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

梦旅人picnic 2024-07-16 18:16:44

您应该使用其他控件作为源,而不是参数。
该参数必须是常量,在您的情况下可以是 -5。

我目前还没有接近 VS,所以语法可能不准确,但是,它是这样的:(

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

转换器将接收 -5 作为字符串,并且必须在使用它之前将其转换为数字。)

根据我的经验,它最好使用 DependecyProperty XXX 的 OnXXXChanged 回调,并且不要将同一窗口/根控件中的控件相互绑定。
原因之一是您稍后可能希望将它们绑定到外部元素。

或者,使用多重绑定:

<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 和一个转换器,将两个参数转换为您想要的值。

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.

捂风挽笑 2024-07-16 18:16:44

是的..多重绑定对我有用..实际上我尝试发送一个元素作为转换器参数,但它不接受。 这就是为什么我将元素作为值传递给转换器类。

下面是我的示例。

<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>

在窗口调整大小中,必须调整我的第一个 gridview 列的大小,而不是其他两个 gridview 列的大小。
我将列表视图的实际宽度以及总网格视图对象作为元素传递。
如果你使用转换器代码...

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
}

这对我有用...:)

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... :)

提笔书几行 2024-07-16 18:16:44

尽管我怀疑可能有更好的方法来解决您的问题,但我想我已经找到了您想要做的事情的答案。 (您没有提到您的容器是什么类型。例如,StackPanel 会为您处理宽度计算。请参阅下面的 TextBox#2)

首先是 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>

然后是转换器。 我们这里遇到了问题..因为 由于某种原因,Convert 方法的 ConverterParameter 不能是动态值。 因此,我们通过在 Window 的 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。 感谢您的练习:)

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 :)

長街聽風 2024-07-16 18:16:44

如果您的文本框是 LayoutRoot 的直接子级,只需在文本框中设置以下属性

HorizontalAlignment="Stretch"

If your textbox is a direct child of LayoutRoot, just set the the following property in your textbox

HorizontalAlignment="Stretch"
梅倚清风 2024-07-16 18:16:44

根据 http://social .msdn.microsoft.com/Forums/en-US/wpf/thread/7298ceb5-bf56-47aa-a161-5dd99189408b,如果您的转换器派生自 DependencyObject,则可以将 Dependency 属性添加到自定义转换器。

在这种情况下,您甚至可以使用数据绑定将值传递到您在 XAML 中定义转换器(在资源字典中)的那些属性。

According to http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/7298ceb5-bf56-47aa-a161-5dd99189408b, you can add a Dependency property to your custom converter if your converter is derived from DependencyObject.

In that case you could even use data binding to pass values to those properties where you define the converter (in the resource dictionary) in XAML.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文