2008-11-23 30 views
11

Tôi muốn đặt chiều rộng của một TextBlock dựa trên chiều rộng của vùng chứa, trừ các lề được đặt trên TextBlock.WPF - Chuyển giá trị của một điều khiển cho Bộ chuyển đổi để đặt độ rộng trên điều khiển khác

Đây là mã của tôi

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

Và đó hoạt động tốt ngoại trừ một thực tế là TextBlock là 10 đơn vị quá lớn do lề trái và phải bbeing thiết lập để 5.

OK, vì vậy Tôi nghĩ ... Hãy sử dụng một bộ chuyển đổi. Nhưng tôi không biết làm thế nào để vượt qua ActualWidth kiểm soát container của tôi (SEE TRÊN: LayoutRoot).

tôi biết làm thế nào để sử dụng bộ chuyển đổi, và thậm chí chuyển đổi với các thông số, chỉ cần không phải là một tham số như ... Binding ElementName = LayoutRoot, Path = ActualWidth

Ví dụ, tôi không thể làm cho công việc này ...

Tôi hy vọng tôi đã thực hiện điều này đủ rõ ràng và hy vọng bạn có thể trợ giúp vì Google không giúp tôi tối nay.

TIA!

Doug

Trả lời

11

bạn có nghĩa vụ phải sử dụng điều khiển khác làm nguồn chứ không phải thông số. Tham số phải là hằng số và trong trường hợp của bạn có thể là -5.

Tôi không gần VS vào lúc này vì vậy các cú pháp có thể không chính xác, tuy nhiên, nó là một cái gì đó như:

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

(Bộ chuyển đổi sẽ nhận -5 như là một chuỗi và sẽ phải chuyển đổi nó thành một số trước khi sử dụng nó.)

Từ kinh nghiệm của tôi tốt hơn là sử dụng gọi lại OnXXXChanged của DependecyProperty XXX, và không ràng buộc các điều khiển trong cùng một cửa sổ/điều khiển gốc cái khác. Một trong những lý do cho điều này là bạn có thể muốn liên kết chúng với một phần tử bên ngoài sau này.

Hoặc cách khác, sử dụng 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> 

và và phần mềm convert mà chuyển đổi hai tham số với giá trị mà bạn muốn.

+0

Cảm ơn Danny. Điều này làm việc tốt. Nhưng tôi đã hy vọng không phải mã cứng giá trị tham số. Tôi không biết rằng tham số cần phải là một hằng số. Cảm ơn! – Doug

+0

Cảm ơn bạn rất nhiều, rất hữu ích! – Jacob

3

Mặc dù tôi nghi ngờ có thể có cách tốt hơn để giải quyết vấn đề của bạn, tôi nghĩ tôi có câu trả lời cho những gì bạn muốn làm. (Bạn đã không đề cập gì gõ container của bạn là. Một StackPanel ví dụ chăm sóc của việc tính toán chiều rộng cho bạn. Xem TextBox # 2 dưới đây)

Đầu tiên là 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> 

Tiếp theo Chuyển đổi. Chúng tôi gặp sự cố ở đây .. kể từ the ConverterParameter for the Convert methods cannot be a dynamic value vì một số lý do. Vì vậy, chúng tôi lẻn vào Margin Textbox thông qua một tài sản công cộng của bộ chuyển đổi mà chúng tôi đặt trong ctor của Window. 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. Cảm ơn tập thể dục :)

+0

Thnaks Gishu! Mẫu của bạn đã giúp tôi tìm hiểu thêm về trình chuyển đổi. Câu trả lời của bạn đã hiệu quả, tôi đã chấm dứt câu trả lời của danny là câu trả lời vì đó là giải pháp mà tôi đã sử dụng. Tôi đã mệt mỏi và lười biếng và anh ta, ít linh hoạt hơn, ít mã hơn. Cảm ơn! – Doug

+0

Làm thế nào tôi bị ám ảnh bởi nhiều giải pháp không hoạt động được, cho đến khi tôi tìm được giải pháp này! Cảm ơn – nemesisfixx

0

Nếu textbox của bạn là một đứa trẻ trực tiếp của LayoutRoot, chỉ cần thiết lập các thuộc tính sau đây trong hộp của bạn

HorizontalAlignment="Stretch" 
5

ràng buộc công trình đối với tôi yes..multi .. thực sự tôi đã cố gắng để gửi một phần tử như là một tham số convereterparameter, nhưng nó không chấp nhận. thats lý do tại sao tôi đã thông qua các yếu tố như là một giá trị cho lớp chuyển đổi.

dưới đây là ví dụ của tôi ..

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

Trong cửa sổ thay đổi kích thước, gridviewcolumn đầu tiên của tôi cần phải được thay đổi kích cỡ, không phải là hai GridViewColumn khác .. i qua ActualWidth của listview và cũng tổng đối tượng GridView như một yếu tố .. nếu bạn đi mã chuyển đổi ...

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 
} 

này làm việc cho tôi ... :)

0

Theo http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/7298ceb5-bf56-47aa-a161-5dd99189408b, bạn có thể thêm thuộc tính Phụ thuộc vào công cụ chuyển đổi tùy chỉnh của mình nếu trình biến đổi của bạn có nguồn gốc từ DependencyObject.

Trong trường hợp đó, bạn thậm chí có thể sử dụng ràng buộc dữ liệu để chuyển giá trị cho các thuộc tính mà bạn xác định trình chuyển đổi (trong từ điển tài nguyên) trong XAML.

Các vấn đề liên quan