2009-02-10 12 views
10

Mam multilinny przycisk radiowy i chcę, aby punkt znajdował się po lewej stronie zawartości (domyślnie) wyrównany do górnej części kontrolki przycisku opcji. Jaki jest najprostszy sposób to zrobić w XAML?Jak ustawić bullet RadioButton na górze?

+0

Zaktualizowałem mój post, to wydaje się działać. – bendewey

Odpowiedz

16

Uwaga: Należy sprawdzić Rachel's answer - bierze ten jeden krok dalej w sposób ogólny szablon


Przede wszystkim nie trać czasu z VerticalAlignment lub VerticalContentAlignment (lub nawet ControlTemplate). Nie zamierzają robić tego, czego się chce, lub czego mogą się spodziewać.

Jak opisano w artykule MSDN a BulletDecorator (która jest formantem, który CheckBox i RadioButton używa do renderowania przycisku radiowego/kontrolnego) automatycznie ustawi pozycję ikony. Nie masz nad tym żadnej dodatkowej kontroli:

Punktor zawsze wyrównuje się z pierwszym wierszem tekstu, gdy obiekt Dziecko jest obiektem tekstowym. Jeśli obiekt Child nie jest obiektem tekstowym, bullet wyrównuje się do środka obiektu Child.

Chyba zmienić szablon sterowania (niepotrzebnych) będziesz w stanie umieścić ikonę radio/wyboru u góry, jeśli treść jest tylko tekst.

Więc jeśli zrobisz coś takiego, to nie będzie dobrze wyglądać, ponieważ nie będziesz w stanie przesunąć ikony, niezależnie od tego, ile próbujesz ustawić, aby ustawić właściwości VerticalAlignment.

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

ALE szczęście można umieścić prawie wszystko, co chcesz w TextBlock korzystając InlineUIContainer. Tekst (lub treść) w pierwszym wierszu automatycznie określi pozycję ikony. Jeśli chcesz coś pod spodem pierwszej linii, która nie jest tekst, wystarczy użyć <Linebreak/> a następnie <InlineUIContainer/>

Oto przykład, że ma zbyt duży TextBox pokazać wyraźniej, co się dzieje.

<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

Bardzo przydatna wskazówka. Dzięki! –

+0

ha Właśnie zauważyłem, że mam VerticalAlignment = "Top" po tym, jak powiedziałem, że to nie było konieczne. Myślę, że prawdopodobnie nie jest tutaj –

+1

Domyślny styl WPF RadioButton nie używa już BulletDecorator w Windows 8 (aero2). Wygląda na to, że nie wymaga tego hackowania i możesz po prostu dodać Grid. Nadal potrzebujesz tego hackowania w systemie Windows XP (luna). Może Windows 7 (aero) jest taki sam jak Windows 8, ale nie mogę tego sprawdzić w tej chwili. – Zodman

2

Zastąpić Control.Template dla RadioButton. Oto przykład z MSDN Radio Button Control Template Example

Jeśli nie chcesz zastąpić Control.Template dla przycisku radiowego, możesz uczynić zawartość Wrapped TextBlock. zobaczyć tę próbkę

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

Miałem nadzieję, że zrobię to bez konieczności nadpisywania szablonu przycisku radiowego, ponieważ wyrównanie jest jedyną rzeczą, którą chcę zmienić. –

+0

Czy chcesz, aby przycisk radiowy znajdował się nad tekstem, czy chcesz mieć przycisk obok siebie z przyciskiem ustawionym w górnej części wiersza (jak obok akapitu)? – bendewey

+0

I chciałbym to zrobić również dla CheckBox, które powinny mieć to samo rozwiązanie. –

13

I został zbudowany stosunkowo ogólny szablon w oparciu o Simon Weaver's answer który może być używany w większości przypadków bez konieczności pamiętania, aby dostosować RadioButton.Content cały czas.

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

Aby wyjaśnić, jak szablon działa:

  • TextBlock jest tam, ponieważ domyślnie kula RadioButton wyrównany względem pierwszego wiersza tekstu, jeśli treść jest obiektem Tekst (a Label będzie nie działa)

  • LineBreak jest owinąć zawartość do nowej linii, więc powstaje pierwsza linia

  • InlineUIContainer jest tak możemy umieścić zawartość nietekstową do TextBlock

  • ContentPresenter jest utrzymanie rzeczywistej treści, a to ma negatywny górny margines do usuwania przestrzeń pozostawioną przez obiekt LineBreak.

Oto kilka przykładów treści:

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

A jak to wygląda:

enter image description here

Jedyne co naprawdę nie jestem zadowolony jest ujemny górny margines dla ContentPresenter jest zakodowana na stałe, ponieważ jeśli kiedykolwiek zmienisz rozmiar czcionki, musisz ręcznie dostosować ten margines.

Prawdopodobnie nie byłoby tak trudno zbudować konwerter dla właściwości Margin który oblicza wysokość przełamania linii ({TemplateBinding FontSize}?), Lub nawet rozszerzona wersja kontroli RadioButton która ma ten problem domyślnie, ale na razie mam się dobrze z twardym kodowaniem -21 w oparciu o domyślny rozmiar czcionki mojej aplikacji.

Ponadto, warto dodać kilka TemplateBindings do RadioButton w szablonie, jeśli chcesz dziedziczyć inne właściwości z oryginalnego RadioButton, takie jak marginesy, dopełnienie, wyrównanie, itp ja tylko związany IsChecked dla celów utrzymywanie prostoty.

+1

Wygląda na to, że będzie to bardzo przydatne, przyjemne zadanie. –

+0

świetna :-) dzięki –

+0

Korzystanie z szablonu w jakiś sposób zatrzymuje przycisk radiowy od używania GroupName. Oznacza to, że w powyższym przykładzie użytkownik może sprawdzić wszystkie trzy opcje, co oznacza, że ​​nie jest już przyciskiem radiowym. – redsolo

Powiązane problemy