2010-04-17 15 views
8

Załóżmy, że masz okno z wieloma przyciskami, takimi jak Ok/Cancel lub Yes/No/Cancel. Wszystkie przyciski muszą mieć tę samą szerokość. Oczywiście można tego dokonać, po prostu zgadując liczbę i łącząc wszystkie z nich do tej liczby.Przyciski WPF tej samej/zalecanej szerokości

Czy istnieje lepszy sposób na zrobienie tego, który bierze pod uwagę preferowane/zalecane rozmiary (jak szeroki powinien być przycisk Ok?) To nie jest retoryczne pytanie, właściwie nie znam odpowiedzi!), co jest potrzebne w tekście najdłuższego napisu, co się stanie, jeśli rozmiar czcionki się zwiększy itp.?

+0

Proszę nie próbować kodować rozmiaru interfejsu użytkownika i takich. Jest to zła praktyka, biorąc pod uwagę internacjonalizację i (w mniejszym stopniu teraz, gdy WPF używa "niezależnych od rozdzielczości jednostek") różnych rozmiarów i ekranów DPI. Mamy do dyspozycji panele układów. Oni są dobrzy. –

+0

Przyciski mają być 50dlu x 23dlu. WPF nie obsługuje jednostek dialogowych; więc prawie utknąłeś. –

Odpowiedz

9

Istnieje kilka sposobów, aby to zrobić:

1) użyć siatki do układu. Każdy przycisk otrzymuje własną kolumnę, która ma rozmiar gwiazdy. W ten sposób wszystkie kolumny są tej samej wielkości:

<Grid> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="*" /> 
     <ColumnDefinition Width="*" /> 
     <ColumnDefinition Width="*" /> 
    </Grid.ColumnDefinitions> 
    <Button Grid.Column="0">Yes</Button> 
    <Button Grid.Column="1">No</Button> 
    <Button Grid.Column="2">Cancel</Button> 
</Grid> 

2) Możesz mieć jedną pozycję jako „master” i wielkości wiążą szerokość wszystkich innych, aby szerokość tego elementu.

<StackPanel Orientation="Horizontal"> 
    <Button Name="MasterButton" Width="100">Yes</Button> 
    <Button> 
     <Button.Width> 
      <Binding ElementName="MasterButton" Path="Width"/> 
     </Button.Width> 
     No 
    </Button> 
</StackPanel> 

EDIT: W rzeczywistym kodzie, prawdopodobnie będzie musiał width = "auto". Ponieważ pozostałe szerokości są oparte na "szerokości wzorcowej", należy wybrać przycisk o najszerszej szerokości (najszerszy tekst).

+0

+1 za polecanie używania paneli w pierwszej sugestii, ale naprawdę jestem przeciwny rozmiarom twardych interfejsów. –

+0

W drugim przypadku miało to na celu wykazanie, że wiązanie działa. –

+5

Czy jednolita siatka nie byłaby dobrym rozwiązaniem? – henon

0

W najbardziej ogólnym przypadku chcesz utworzyć styl w swojej sekcji, a następnie zastosować ten styl zgodnie z potrzebami. Teraz po zmianie stylu wszystkie przyciski zmieniają się.

Lub możesz zmienić zawartość przycisku, aby autosizes do tekstu.

+0

Dzięki. Ale, popraw mnie, jeśli się mylę, ale czy nie spowodowałoby to autosize przycisku do tekstu, złamanie wymogu, że wszystkie przyciski mają tę samą szerokość? I czy nie jest to rozwiązanie stylowe, tylko szczególny sposób implementacji "zgadnij liczbę i hardwire wszystkie przyciski do tego numeru"? – rwallace

+0

Ah ... Rozumiem teraz twoje wymagania, przepraszam! Daniel ma znacznie lepszą odpowiedź. – Dave

2

Zgodnie z wytycznymi dotyczącymi interakcji użytkownika MS User Experience dla systemów Windows 7 i Windows Vista (p61), standardowe wymiary przycisków poleceń to rzeczywisty rozmiar DLP 50x14 (75x23 pikseli). Wytyczne sugerują, że "próbujesz pracować z [tymi] domyślnymi szerokościami i wysokościami". Oczywiście, jeśli potrzebujesz większej szerokości, aby pasowała do przezroczystej etykiety, wybierz większą szerokość.

+0

Przyciski mają być jednostkami dialogowymi 50x14. Twoja konwersja na piksele jest błędna; przynajmniej na moim komputerze, gdzie używam 'Georgia 14pt'. Dlatego istnieją jednostki dialogowe - aby ludzie przestali używać rozmiarów pikseli. –

4

Użyj „master” kontrolę, jak w odpowiedzi Daniela, ale wiążą się z „ActualWidth” atrybut zamiast „szerokość”:

<StackPanel Orientation="Horizontal"> 
    <Button Name="MasterButton">Yes</Button> 
    <Button> 
     <Button.Width> 
      <Binding ElementName="MasterButton" Path="ActualWidth"/> 
     </Button.Width> 
     No 
    </Button> 
</StackPanel> 

ten sposób wartość jest pobierana z kontrolą mistrza w perspektywie czas, po uwzględnieniu minimalnej i maksymalnej szerokości oraz wszystkich pozostałych obliczeń układu. Wiązanie z "Width" wiąże się z tym, co zdarzy się wstawić do atrybutu w czasie kompilacji, która może nie być faktycznie użytą szerokością.

Ponadto, wiązanie można zapisać krócej jak

<Button Width="{Binding ElementName=MasterButton, Path=ActualWidth}"/> 
7

Innym, być może prostsza, sposobem, aby to zrobić, to użyć właściwości SharedSizeGroup na zajęciach ColumnDefinition i RowDefinition.

Kolumny (i wiersze) w siatce WPF mogą automatycznie zmieniać rozmiar w celu dopasowania do ich zawartości - w przypadku użycia SharedSizeGroup kolumny z tą samą nazwą grupy mają wspólną logikę zmiany rozmiaru.

Xaml wyglądałby tak ...

<Grid Grid.IsSharedSizeScope="True"> 

    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="*" /> 
     <ColumnDefinition SharedSizeGroup="Buttons" /> 
     <ColumnDefinition SharedSizeGroup="Buttons" /> 
     <ColumnDefinition SharedSizeGroup="Buttons" /> 
    </Grid.ColumnDefinitions> 

    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="*" /> 
    </Grid.RowDefinitions> 

    <Button Grid.Column="1" 
      HorizontalAlignment="Stretch" 
      VerticalAlignment="Center" 
      Content="Ok" 
      Margin="4" /> 

    <Button Grid.Column="2" 
      HorizontalAlignment="Stretch" 
      VerticalAlignment="Center" 
      Content="Cancel" 
      Margin="4" /> 

    <Button Grid.Column="3" 
      HorizontalAlignment="Stretch" 
      VerticalAlignment="Center" 
      Content="Long Button Caption" 
      Margin="4" /> 
</Grid> 
0

Te odpowiedzi są świetne, jeśli masz ustaloną liczbę lub stały układ dla przycisków, ale jeśli tak jak ja istnieje szereg dynamicznych przycisków pochodzących z wiążącym i zawarte w ItemsControl to nie jest wykonalne. Ale jest prosty sposób i nadal wymaga użycia właściwości sharedsize siatki.

DataTemplate:

<DataTemplate x:Key="ODIF.Mapping"> 
    <Button HorizontalContentAlignment="Left" Background="#FFEEEEEE" BorderBrush="#FFBDBDBD"> 
     <Grid> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="Auto" SharedSizeGroup="PluginButtonsWidth"/> 
      </Grid.ColumnDefinitions> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="Auto" SharedSizeGroup="PluginButtonsIconHeight"/> 
       <RowDefinition Height="Auto" SharedSizeGroup="PluginButtonsNameHeight"/> 
      </Grid.RowDefinitions> 
      <Image Width="32" Height="32" Source="{Binding PluginIcon}" RenderOptions.BitmapScalingMode="HighQuality"/> 
      <TextBlock Grid.Row="1" Text="{Binding PluginName}"/> 
     </Grid> 
    </Button> 
</DataTemplate> 

kontener nadrzędny:

<ItemsControl ItemsSource="{Binding MappingPlugins, ElementName=page}" ItemTemplate="{StaticResource ODIF.Mapping}"> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <WrapPanel Grid.IsSharedSizeScope="True"/> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
</ItemsControl> 

Zasadniczo treść przycisk może sam być filtr polaryzacyjny, który następnie można umieścić etykiety i ikony jak potrzebne, ale mimo przycisków nie znajdują się w tej samej siatce (każda z nich jest ich własną), ale sieć może nadal udostępniać jej rozmiar, o ile ustawiono właściwość kontenera głównego (ItemsControl) z Grid.IsSharedSizeScope na wartość True.

Spowoduje to, że siatka zawartości każdego przycisku będzie miała taki sam dokładny rozmiar w oparciu o największy, bez konieczności posiadania samych przycisków we wstępnie zdefiniowanej siatce.

Powiązane problemy