14

我想根据容器的宽度设置 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>

除了由于左右边距设置为 5 导致 TextBlock 太大了 10 个单位之外,这非常有效。

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

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

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

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

我希望我说得足够清楚,并希望您能提供帮助,因为今晚谷歌对我没有帮助。

4

5 回答 5

14

你应该使用另一个控件作为源,而不是参数。该参数必须是常数,在您的情况下可以是-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>

和一个转换器,它将两个参数转换为您想要的值。

于 2008-11-23T05:46:45.050 回答
7

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

下面是我的例子..

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

在窗口调整大小时,我的第一个 gridviewcolumn 必须调整大小,而不是其他两个 gridviewcolumn ..我传递了 listview 的 Actualwidth 和总 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
}

这对我有用...... :)

于 2009-07-30T10:41:05.060 回答
3

尽管我怀疑可能有更好的方法来解决您的问题,但我想我对您想要做的事情有一个答案。(您没有提到您的容器是什么类型。例如 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 中设置的 Converter 的公共属性潜入 Textbox Margin。 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。谢谢你的练习:)

于 2008-11-23T06:19:07.263 回答
0

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

HorizontalAlignment="Stretch"
于 2009-01-05T19:01:41.040 回答
0

根据http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/7298ceb5-bf56-47aa-a161-5dd99189408b,如果您的转换器源自依赖对象。

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

于 2012-07-03T16:05:03.820 回答