2008-11-23 6 views
11

ich die Breite eines Textblock auf der Breite des Containers auf Basis gesetzt werden soll, abzüglich der Ränder auf dem Textblock gesetzt.WPF - Übergeben Sie den Wert einer Steuerung zu einem Konverter auf eine andere Steuerung die Breite einzustellen

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 gesetzt bbeing bis 5.

OK, so Ich dachte ... Lass uns einen Konverter benutzen. Aber ich weiß nicht, wie ich die ActualWidth meines Containersteuerelements übergeben kann (siehe oben: LayoutRoot).

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

Zum Beispiel kann ich nicht diese Arbeit machen ...

Ich hoffe, ich habe das klar genug gemacht und hoffe, dass Sie helfen können, weil Google heute Nacht keine Hilfe für mich ist.

TIA!

Doug

Antwort

11

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

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

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

(Der Konverter erhält -5 als String und konvertiert hat, um es in eine Nummer, bevor Sie es verwenden.)

Aus meiner Erfahrung ist es besser, den OnXXXChanged Rückruf von DependecyProperty XXX zu verwenden, und Steuerelemente innerhalb desselben Fensters/Stammsteuerelements nicht zu einem anderen zu binden. Einer der Gründe dafür ist, dass Sie diese später an ein externes Element binden möchten.

Oder alternativ verwenden 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 Konverter, der die beiden Parameter auf den Wert konvertiert Sie wollen.

+0

Danke Danny. Das hat gut funktioniert. Aber ich hatte gehofft, den Parameterwert nicht hart codieren zu müssen. Ich wusste nicht, dass der Parameter eine Konstante sein musste. Vielen Dank! – Doug

+0

Vielen Dank, so hilfreich! – Jacob

3

Obwohl ich vermute, dass es möglicherweise einen besseren Weg gibt, um Ihr Problem zu lösen, denke ich, dass ich eine Antwort für das habe, was Sie tun möchten. (Sie erwähnen nicht, was Ihr Container-Typ ist. Ein Stackpanel zum Beispiel kümmert sich um die Breitenberechnung für Sie. Siehe TextBox # 2 unten)

zuerst 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 hier ein Problem .. seit the ConverterParameter for the Convert methods cannot be a dynamic value aus irgendeinem Grund. Also schleichen wir uns die Textbox Margin über eine öffentliche Eigenschaft des Converters ein, die wir in Window's ctor setzen. 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 :)

+0

Thnaks Gishu! Ihre Probe hat mir geholfen, mehr über Konverter zu lernen. Obwohl Ihre Antwort funktionierte, beendete ich die Antwort von Danny als DIE Antwort, weil es die Lösung war, die ich verwendete. Ich war müde und faul und sein, obwohl weniger flexibel, war weniger Code. Vielen Dank! – Doug

+0

Wie ich von den vielen Lösungen geplagt wurde, die nicht funktionieren konnten, bis ich diese gefunden habe! Vielen Dank – nemesisfixx

0

Wenn Ihr Textbox ein direkter Nachkomme von LayoutRoot ist, nur die folgende Eigenschaft in Ihrem Textfeld gesetzt

HorizontalAlignment="Stretch" 
5

yes..multi Werke für mich bindend .. eigentlich habe ich versucht zu sende ein Element als Konvertierparameter, aber es akzeptiert nicht. Deshalb habe ich das Element als Wert an die Konverterklasse ü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 Actual von Listview und auch insgesamt gridview Objekt als Element übergeben .. , wenn Sie gehen der Konverter 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 
} 

dies für mich gearbeitet ... :)