WPF - Übergeben Sie den Wert einer Steuerung zu einem Konverter auf eine andere Steuerung die Breite einstellen

StackOverflow https://stackoverflow.com/questions/312044

Frage

Ich möchte die Breite eines Textblock auf der Breite des Containers auf Basis einzustellen, abzüglich der Ränder auf dem Textblock gesetzt.

Hier ist mein 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>

Und das funktioniert gut, außer der Tatsache, dass der Textblock 10 Einheiten zu groß ist aufgrund der linken und rechten Rand auf 5 gesetzt bbeing.

OK, also dachte ich ... Lassen Sie uns einen Converter verwenden. Aber ich weiß nicht, wie die Actual meines Containersteuer passieren (siehe oben: LayoutRoot).

Ich weiß, wie Konverter zu verwenden, und auch Wandler mit Parametern, nur kein Parameter wie ... Binding Elementname = LayoutRoot, Path = Actual

Zum Beispiel, kann ich diese Arbeit nicht machen ...

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

Ich hoffe, dass ich dies klar genug gemacht und hoffen, dass Sie helfen können, da Google keine Hilfe für mich heute Abend.

TIA!

Doug

War es hilfreich?

Lösung

Sie sollten die andere Steuerung als Quelle verwenden, nicht der Parameter. Der Parameter hat eine Konstante und in Ihrem Fall sein -5 sein kann.

Ich bin nicht in der Nähe von VS im Moment so die Syntax vielleicht ungenau, jedoch ist es so etwas wie:

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

(Der Konverter erhält -5 als String und muss es in eine Zahl umgewandelt werden, bevor sie verwendet wird.)

Aus meiner Erfahrung ist es besser, die OnXXXChanged Rückruf von DependecyProperty XXX zu verwenden, und nicht binden Kontrollen im selben Fenster / root Steuer einem zum anderen. Einer der Gründe dafür ist, dass man sie an ein externes Element später binden möchten.

oder alternativ Verwendung mehrbindigen:

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

und und einen Wandler, der die beiden Parameter auf den Wert konvertiert Sie wollen.

Andere Tipps

yes..multi Werke für mich bindend .. eigentlich habe ich versucht, ein Element als convereterparameter zu schicken, aber es ist nicht zu akzeptieren. thats, warum ich das Element als Wert an die Konverter-Klasse übergeben.

unten ist mein Beispiel ..

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

Im Fenster Größe ändern, meine erste Gridviewcolumn Größe geändert werden muss, nicht die beiden anderen gridviewcolumns .. i bestehen Actual von Listview und auch insgesamt gridview Objekt als Element .. wenn Sie den Konverter Code gehen ...

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
}

Dies ist für mich ... :)

Obwohl ich vermute, es kann eine bessere Art und Weise sein, Ihr Problem zu lösen, ich glaube, ich habe eine Antwort für das, was Sie tun mögen. (Sie nicht erwähnt, was Ihre Container-Typ ist. Ein Stackpanel zum Beispiel kümmert sich um die Breitenberechnung für Sie. Siehe TextBox # 2 unten)

Zuerst wird die 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>

Als nächstes wird der Converter. Wir haben ein Problem hier .. da die Converter für die Convert Methoden können nicht ein dynamischer Wert aus irgendeinem Grund sein. So schleichen wir in der Textbox Margin über eine öffentliche Eigenschaft des Converter, die wir in Fenster Ctor gesetzt. 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. Vielen Dank für die Übung:)

Wenn Ihr Textbox ein direkter Nachkomme von LayoutRoot ist, nur legen Sie die folgende Eigenschaft in der Textbox

HorizontalAlignment="Stretch"

Nach http: //social.msdn.microsoft.com/Forums/en-US/wpf/thread/7298ceb5-bf56-47aa-a161-5dd99189408b , können Sie eine Abhängigkeitseigenschaft zu Ihren benutzerdefinierten Konverter hinzufügen, wenn Ihr Konverter von abgeleitet ist DependencyObject.

In diesem Fall könnten Sie sogar Daten verwenden verbindende Werte für diese Eigenschaften zu übergeben, wo Sie den Konverter definieren (im Ressourcenverzeichnis) in XAML.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top