2009-02-10 33 views

Trả lời

16

Note: Hãy chắc chắn để kiểm tra Rachel's answer - cô mất một giai đoạn này thêm vào một lớp tổng quát


Trước hết đừng lãng phí thời gian của bạn với VerticalAlignment hoặc VerticalContentAlignment (hoặc thậm chí ControlTemplate). Họ sẽ không làm những gì bạn muốn hoặc có thể mong đợi.

Như được mô tả trên MSDN a BulletDecorator (là điều khiển mà CheckBox và RadioButton sử dụng để hiển thị nút radio/kiểm tra) sẽ tự động đặt vị trí của biểu tượng. Bạn không có quyền kiểm soát bổ sung đối với điều này:

Dấu đầu dòng luôn khớp với dòng đầu tiên của văn bản khi đối tượng con là đối tượng văn bản. Nếu đối tượng Child không phải là đối tượng văn bản, thì Bullet sẽ căn giữa với đối tượng con.

Trừ khi bạn thay đổi mẫu điều khiển (không cần thiết), bạn sẽ chỉ có thể định vị biểu tượng radio/kiểm tra ở trên cùng nếu nội dung là văn bản.

Vì vậy, nếu bạn làm một cái gì đó như thế này nó sẽ không tốt vì bạn sẽ không thể di chuyển biểu tượng cho dù có bao nhiêu thuộc tính VerticalAlignment bạn cố đặt.

<RadioButton> 
    <StackPanel> 
     <TextBlock Text="First line"/> 
     <TextBlock Text="Something else"/> 
    </StackPanel> 
</RadioButton> 

NHƯNG may mắn thay bạn có thể đặt khá nhiều bất cứ điều gì bạn muốn trong một TextBlock sử dụng InlineUIContainer. Văn bản (hoặc nội dung) trong dòng đầu tiên sẽ tự động định vị vị trí của biểu tượng. Nếu bạn muốn một cái gì đó bên dưới dòng đầu tiên không phải là văn bản, chỉ cần sử dụng <Linebreak/> và sau đó <InlineUIContainer/>

Đây là một ví dụ có quá khổ TextBox để hiển thị rõ hơn những gì đang xảy ra.

<RadioButton> 

    <TextBlock VerticalAlignment="Top" TextWrapping="Wrap"> 

     <TextBlock Text="Products with &lt;" VerticalAlignment="Center" Margin="0,0,5,0"/> 

     <InlineUIContainer BaselineAlignment="Center"> 
      <TextBox FontSize="30" Width="25" Text="10" Margin="0,0,5,0"/>   
     </InlineUIContainer> 

     <TextBlock VerticalAlignment="Center" Margin="0,0,5,0"> 
      <Run Text="days" FontWeight="Bold"/> 
      <Run Text="inventory" /> 
     </TextBlock> 

     <LineBreak/>  

     <InlineUIContainer> 
      <StackPanel> 
       <CheckBox Content="Include unsold products" /> 
       <CheckBox Content="Include something else" /> 
      </StackPanel> 
     </InlineUIContainer> 

    </TextBlock> 
</RadioButton> 
+0

Một mẹo rất hữu ích. Cảm ơn! –

+0

ha Tôi chỉ nhận thấy tôi có VerticalAlignment = "Top" sau khi đã nói rằng nó không cần thiết. Tôi nghĩ rằng nó có lẽ không phải là ở đây –

+1

Kiểu mặc định của WPF RadioButton không còn sử dụng BulletDecorator trong Windows 8 (aero2). Dường như nó không yêu cầu hack này, và bạn chỉ cần thêm một Grid. Bạn vẫn cần hack này trên Windows XP (luna). Có lẽ Windows 7 (aero) cũng giống như Windows 8 nhưng tôi không thể kiểm tra điều này vào lúc này. – Zodman

2

Ghi đè Control.Template cho RadioButton. Dưới đây là ví dụ từ MSDN Radio Button Control Template Example

Nếu bạn không muốn ghi đè Control.Template cho nút radio, bạn có thể đặt nội dung thành một TextBlock được bao bọc. xem mẫu này

<RadioButton Name="radioButton1"> 
    <TextBlock TextWrapping="Wrap">Here is some multiline text that does some wrapping</TextBlock> 
</RadioButton> 
+0

Tôi đã hy vọng để làm điều đó mà không cần phải ghi đè lên các mẫu nút radio vì sự liên kết là điều duy nhất tôi muốn thay đổi. –

+0

Bạn có muốn nút radio nằm ở trên cùng của văn bản hay bạn muốn nút radio cạnh nhau với nút được căn chỉnh trên đầu hàng (như bên cạnh một đoạn)? – bendewey

+0

Và tôi cũng muốn làm điều đó cho CheckBox, cần có giải pháp tương tự. –

13

tôi đã xây dựng một mẫu tương đối chung chung dựa trên Simon Weaver's answer có thể được sử dụng trong hầu hết các tình huống mà không cần phải nhớ để tùy chỉnh RadioButton.Content tất cả các thời gian của bạn.

<ControlTemplate x:Key="MultiLineRadioButtonTemplate" TargetType="{x:Type RadioButton}"> 
    <RadioButton IsChecked="{TemplateBinding IsChecked}"> 
     <TextBlock> 
      <LineBreak /> 
      <InlineUIContainer> 
       <ContentPresenter Margin="0,-21,0,8" 
            Content="{TemplateBinding ContentPresenter.Content}" 
            ContentTemplate="{TemplateBinding ContentPresenter.ContentTemplate}"/> 
      </InlineUIContainer> 
     </TextBlock> 
    </RadioButton> 
</ControlTemplate> 

Để giải thích cách thức các mẫu hoạt động:

  • Các TextBlock là có vì theo mặc định, đạn RadioButton thẳng hàng với dòng đầu tiên của văn bản nếu nội dung là một đối tượng văn bản (một Label sẽ không làm việc)

  • các LineBreak là để bọc các nội dung vào một dòng mới, do đó, dòng đầu tiên được tạo

  • Các InlineUIContainer là vì vậy chúng tôi có thể đặt nội dung phi văn bản thành một TextBlock

  • Các ContentPresenter là để giữ nội dung thực tế, và nó có một lề trên tiêu cực để loại bỏ các không gian còn lại của đối tượng LineBreak.

Dưới đây là một số nội dung ví dụ:

<StackPanel> 
    <RadioButton Template="{StaticResource MultiLineRadioButtonTemplate}"> 
     <StackPanel> 
      <Label Content="Option 1" /> 
      <StackPanel> 
       <CheckBox Content="Some setting" /> 
       <CheckBox Content="Some other setting" /> 
      </StackPanel> 
     </StackPanel> 
    </RadioButton> 

    <RadioButton Template="{StaticResource MultiLineRadioButtonTemplate}"> 
     <StackPanel> 
      <Label Content="Option 2" /> 
      <DataGrid AutoGenerateColumns="False" Height="100"> 
       <DataGrid.Columns> 
        <DataGridTextColumn Header="Id" /> 
        <DataGridTextColumn Header="Date" /> 
        <DataGridTextColumn Header="Total" /> 
        <DataGridTextColumn Header="Count" /> 
       </DataGrid.Columns> 
      </DataGrid> 
     </StackPanel> 
    </RadioButton> 


    <RadioButton Template="{StaticResource MultiLineRadioButtonTemplate}"> 
     <StackPanel> 
      <Label Content="Option 3" /> 
      <TextBlock TextWrapping="WrapWithOverflow" Margin="2"> 
       Lorem ipsum dolor sit amet, consectetur adipisicing elit, 
       sed do eiusmod tempor incididunt ut labore et dolore magna 
       aliqua. Ut enim ad minim veniam, quis nostrud exercitation 
       ullamco laboris nisi ut aliquip ex ea commodo consequat. 
       Duis aute irure dolor in reprehenderit in voluptate velit 
       esse cillum dolore eu fugiat nulla pariatur. Excepteur sint 
       occaecat cupidatat non proident, sunt in culpa qui officia 
       deserunt mollit anim id est laborum. 
      </TextBlock> 
     </StackPanel> 
    </RadioButton> 
</StackPanel> 

Và làm thế nào nó trông giống:

enter image description here

Điều duy nhất tôi thực sự không hài lòng về là lề trên tiêu cực đối với các ContentPresenter được mã hóa cứng, bởi vì nếu bạn thay đổi kích thước phông chữ của mình, bạn phải tự điều chỉnh lề đó. Có thể sẽ không khó để xây dựng bộ chuyển đổi cho thuộc tính Margin tính toán chiều cao của ngắt dòng ({TemplateBinding FontSize}?) Hoặc thậm chí là phiên bản mở rộng của điều khiển RadioButton có hành vi này theo mặc định, nhưng bây giờ tôi ổn với mã hóa -21 dựa trên kích thước phông chữ mặc định của ứng dụng của tôi.

Ngoài ra, bạn có thể muốn thêm một số TemplateBindings đến RadioButton trong Template nếu bạn muốn kế thừa tài sản khác từ bản gốc RadioButton, chẳng hạn như lợi nhuận, đệm, sự liên kết, vv Tôi chỉ bị ràng buộc để IsChecked với mục đích giữ nó đơn giản.

+1

Điều đó có vẻ như nó sẽ đến trong công việc thực sự tiện dụng, tốt đẹp. –

+0

tuyệt vời :-) cảm ơn –

+0

Sử dụng mẫu một số cách dừng nút radio bằng cách sử dụng GroupName. Điều này có nghĩa trong ví dụ trên, người dùng có thể kiểm tra cả ba tùy chọn, điều đó có nghĩa là nó không còn là nút radio nữa. – redsolo

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