2017-01-13 17 views
1

мне нужно создать пользовательский интерфейс следующим образом (вид контроля облако тегов)Создание п число кнопок переменного размера в контейнере

  • п количество кнопок (Count будет определяться во время выполнения)
  • Каждый кнопка будет иметь различную ширину на основе его содержания
  • Max 3 кнопки в строке

Buttons with different widths

Я попытался следующие вещи

  • VariableSizedWrapGrid, как ItemsPanel из GridView (Это требует RowSpan и ColumnSpan быть указано, которые не осуществима в ширине определяется во время выполнения)
  • StackPanel с горизонтальной ориентацией (Все кнопки были расположены в одной строке)

Любые мысли?

+0

Как насчет использования стекольной панели с вертикальной ориентацией и внутри нее stackpanel с горизонтальной ориентацией, содержащей максимум 3 кнопки? – Pratyay

+0

@Pratyay, ну, что можно сделать, но если я добавлю 3 кнопки в каждую горизонтальную стеклянную панель, это может привести к слишком длинным строкам, если все 3 кнопки имеют более длинный контент. Конечно, можно добавить горизонтальную полосу прокрутки, но было бы неплохо избежать горизонтальной полосы прокрутки в моем случае. Любое другое лучшее решение? – praveenDM

+0

Ну, легкий выход из проблемы с длинными строками будет определять MaxWidth для кнопок, которые будут составлять 1/3 от ширины стека (и учитывая разницу между кнопками, которые добавляет панель стека по умолчанию) .., но это приведет к обрыву содержимого (или текст) внутри кнопки. Также учитывая, что вы создаете приложение UWP, оно должно иметь возможность масштабировать любое разрешение экрана без проблем, вы должны переключиться на VariableSizedWrapGrid или проверить размер экрана на событии GridSizeChanged и соответствующим образом заполнить его (что будет иметь серьезные если проблемы не выполняются правильно). – Pratyay

ответ

2

Here - отличный блог-блог о том, как создать WrapPanel на основе ваших требований.

Я создал TagsPanel, основанный на этом блоге, чтобы использовать его в одном из моих приложений. Ключ должен переходить к элементам и получать фактический размер и устанавливать его на основе доступной ширины панели. Смотри ниже.

public class TagsPanel : Panel 
{ 
    protected override Size MeasureOverride(Size availableSize) 
    { 
     // Just take up all of the width 
     Size finalSize = new Size { Width = availableSize.Width }; 
     double x = 0; 
     double rowHeight = 0d; 
     foreach (var child in Children) 
     { 
      // Tell the child control to determine the size needed 
      child.Measure(availableSize); 

      x += child.DesiredSize.Width; 
      if (x > availableSize.Width) 
      { 
       // this item will start the next row 
       x = child.DesiredSize.Width; 

       // adjust the height of the panel 
       finalSize.Height += rowHeight; 
       rowHeight = child.DesiredSize.Height; 
      } 
      else 
      { 
       // Get the tallest item 
       rowHeight = Math.Max(child.DesiredSize.Height, rowHeight); 
      } 
     } 

     // Add the final height 
     finalSize.Height += rowHeight; 
     return finalSize; 
    } 

    protected override Size ArrangeOverride(Size finalSize) 
    { 
     Rect finalRect = new Rect(0, 0, finalSize.Width, finalSize.Height); 

     double rowHeight = 0; 
     foreach (var child in Children) 
     { 
      if ((child.DesiredSize.Width + finalRect.X) > finalSize.Width) 
      { 
       // next row! 
       finalRect.X = 0; 
       finalRect.Y += rowHeight; 
       rowHeight = 0; 
      } 
      // Place the item 
      child.Arrange(new Rect(finalRect.X, finalRect.Y, child.DesiredSize.Width, child.DesiredSize.Height)); 

      // adjust the location for the next items 
      finalRect.X += child.DesiredSize.Width; 
      rowHeight = Math.Max(child.DesiredSize.Height, rowHeight); 
     } 
     return finalSize; 
    } 
} 

и использовать его в GridView, как показано ниже.

<GridView ItemsSource="{Binding tags}" > 
    <GridView.ItemTemplate> 
     <DataTemplate> 
      <Button Content="{Binding ''}" Margin="5"/> 
     </DataTemplate> 
    </GridView.ItemTemplate> 
    <GridView.ItemsPanel> 
     <ItemsPanelTemplate> 
      <local:TagsPanel/> 
     </ItemsPanelTemplate> 
    </GridView.ItemsPanel> 
</GridView> 
+0

Спасибо, именно то, что я хотел! – praveenDM

2

В принципе, VariableSizedWrapGrid относится ко всем своим дочерним элементам одинакового размера. Вы можете использовать ColumnSpan и RowSpan для расширения области дочернего элемента.

Другой способ - создать пользовательский элемент управления WrapPanel, а затем использовать вместо VariableSizedWrapGrid. Это будет определять результат, как вы описали.

+0

UWP не имеет WrapPanel, тогда как тот же доступен в WPF. Вам нужно будет создать пользовательский элемент управления WrapPanel и использовать вместо VariableSizedWrapGrid в xaml. –