2016-01-19 7 views
1

Прежде всего, у меня есть ItemsControl, целью которого является отображение нескольких групп содержимого; внутри каждой группы есть еще один ItemsControl, который предназначен для отображения серверного Button внутри.C#/WPF - равномерно растягивать кнопки в вложенных элементах ItemsControl для заполнения всего пространства

Мой .xaml:

<Window x:Class="CX11TestSolution.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Height="768" 
    Width="1024"> 
<ItemsControl ItemsSource="{Binding HahaList}"> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <Grid> 
       <Grid.RowDefinitions> 
        <RowDefinition Height="Auto" /> 
        <RowDefinition /> 
       </Grid.RowDefinitions> 
       <Label Content="{Binding Name}" /> 
       <ItemsControl Grid.Row="1" 
           ItemsSource="{Binding ItemList}"> 
        <ItemsControl.ItemsPanel> 
         <ItemsPanelTemplate> 
          <UniformGrid Columns="5" /> 
         </ItemsPanelTemplate> 
        </ItemsControl.ItemsPanel> 
        <ItemsControl.ItemTemplate> 
         <DataTemplate> 
          <Button Content="{Binding Name}" /> 
         </DataTemplate> 
        </ItemsControl.ItemTemplate> 
       </ItemsControl> 
      </Grid> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <UniformGrid Columns="1" /> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
</ItemsControl> 

Мои .xaml.cs:

public partial class MainWindow : Window 
{ 
    public IEnumerable<SomeClass> HahaList { get; } 
    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = this; 
     HahaList = new List<SomeClass>() 
     { 
      new SomeClass("Group 1", new List<SomeClass>() { 
       new SomeClass("11"), 
       new SomeClass("12"), 
       new SomeClass("13"), 
       new SomeClass("14"), 
       new SomeClass("15"), 
       new SomeClass("16"), 
      }), 
      new SomeClass("Group 2", new List<SomeClass>() { 
       new SomeClass("21"), 
       new SomeClass("22"), 
       new SomeClass("23"), 
       new SomeClass("24"), 
      }), 
      new SomeClass("Group 3", new List<SomeClass>() { 
       new SomeClass("31"), 
       new SomeClass("32"), 
       new SomeClass("33"), 
      }), 
      new SomeClass("Group 4", new List<SomeClass>() { 
       new SomeClass("41"), 
       new SomeClass("42"), 
      }), 
      new SomeClass("Group 5", new List<SomeClass>() { 
       new SomeClass("52"), 
      }), 
     }; 
    } 
} 

public class SomeClass 
{ 
    public string Name { get; } 
    public IEnumerable<SomeClass> ItemList { get; } 
    public SomeClass(string name, IEnumerable<SomeClass> list) 
    { 
     Name = name; 
     ItemList = list; 
    } 
    public SomeClass(string name) 
    { 
     Name = name; 
    } 
} 

Результат: Result

Так что мой вопрос заключается в том, что как я в равной степени растяните высоту кнопок так, чтобы они заполнят всю площадь?

Я фактически попытался установить ItemsPanel родителя ItemsControl к UniformGrid который имеет Columns 1, и это делает работу, когда количество кнопок в каждой группе не больше, чем 5. Когда оно превышает 5, шестую кнопку переместится в следующую строку, тем самым сокращая первую строку, чтобы каждая группа имела равную высоту. enter image description here Благодарим вас заранее.

ответ

1

Я сделал бы это вручную с помощью сетки. Вы знаете, что существует не более 5 столбцов, поэтому легко определить, сколько столбцов и строк вам понадобится для сетки, которая охватывает все. Используйте приложенное поведение, чтобы динамически устанавливать строки и столбцы сетки во время выполнения, вам также нужно, чтобы флаг указывал, является ли каждая строка «Авто» (заголовки) или «1 *» (равномерно распределенной). Наконец, добавьте поля в SomeClass для столбца и номера строки Grid и привяжите их к вашему XAML.

Возможно, есть способ сделать это в чистом XAML или с помощью собственного класса макета, но метод, который я описываю выше, должен занять всего 10 минут, и его легко проверить и отладить, поэтому вы, вероятно, сохраните у вас много головной боли в долгосрочной перспективе.

UPDATE:

Я просто реализовать мой метод делать это, он требует, чтобы добавить к вашей основной модели представления:

public int RowCount { get; set; } 
    public int ColumnCount {get; set; }  
    public string StarCount { get; set; } 
    public string StarRows { get; set; } 
    public string StarColumns { get; set; } 
    public List<Tuple<SomeClass, bool>> AllItems { get; set; } // second parameter indicates whether it's a header 


    private void UpdateGridLayout() 
    { 
     this.AllItems = new List<Tuple<SomeClass, bool>>(); 

     this.ColumnCount = 5; 
     this.RowCount = HahaList.Sum(x => 1 + (x.ItemList.Count() + this.ColumnCount - 1)/this.ColumnCount); 
     int row = 0; 
     this.StarColumns = String.Join(",", Enumerable.Range(0, this.ColumnCount).Select(i => i.ToString())); // all columns 
     this.StarRows = null; 
     foreach (var section in this.HahaList) 
     { 
      this.AllItems.Add(new Tuple<SomeClass, bool>(section, true)); 
      section.Row = row; 
      section.Column = 0; 
      section.ColumnSpan = this.ColumnCount; 

      row++; 
      if (StarRows != null) 
       StarRows += ","; 
      StarRows += row.ToString(); 
      int column = 0;    
      foreach (var item in section.ItemList) 
      { 
       this.AllItems.Add(new Tuple<SomeClass, bool>(item, false)); 
       item.Row = row; 
       item.Column = column++; 
       item.ColumnSpan = 1; 
       if (column >= this.ColumnCount) 
       {      
        column = 0; 
        row++; 
        if (StarRows != null) 
         StarRows += ","; 
        StarRows += row.ToString(); 
       } 

      } 
      row++; 
     } 
     return; 
    } 

UpdateGridLayout должен быть вызван после того, как вы установили ваш HahaList, если вы хотите, чтобы это поддерживало динамические изменения, то, очевидно, вам придется пройти все это и добавить INPC. Одна заметная разница в этом коде - это добавление свойства «AllItems», в котором есть как заголовки, так и листовые узлы вместе с флагом, указывающим, какой тип каждого из них (я бы сам использовал разные классы, так что вам не нужно это делать).

SomeClass также необходимо несколько дополнительных свойств:

public int Row { get; set; } 
    public int Column { get; set; } 
    public int ColumnSpan { get; set; } 

А вот XAML:

<ItemsControl ItemsSource="{Binding AllItems}"> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <Grid local:GridHelpers.RowCount="{Binding RowCount}" 
        local:GridHelpers.ColumnCount="{Binding ColumnCount}" 
        local:GridHelpers.StarRows="{Binding StarRows}" 
        local:GridHelpers.StarColumns="{Binding StarColumns}"/> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
    <ItemsControl.ItemContainerStyle> 
     <Style> 
      <Setter Property="Grid.Row" Value="{Binding Item1.Row}" /> 
      <Setter Property="Grid.Column" Value="{Binding Item1.Column}" /> 
      <Setter Property="Grid.ColumnSpan" Value="{Binding Item1.ColumnSpan}" /> 
     </Style> 
    </ItemsControl.ItemContainerStyle> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <ContentControl> 
       <ContentControl.Style> 
        <Style TargetType="ContentControl"> 
         <Setter Property="Template"> 
          <Setter.Value> 
           <ControlTemplate> 
            <Label Content="{Binding Item1.Name}" /> 
           </ControlTemplate> 
          </Setter.Value> 
         </Setter> 
         <Style.Triggers> 
          <DataTrigger Binding="{Binding Item2}" Value="false"> 
           <Setter Property="Template"> 
            <Setter.Value> 
             <ControlTemplate> 
              <Button Content="{Binding Item1.Name}" /> 
             </ControlTemplate> 
            </Setter.Value> 
           </Setter> 
          </DataTrigger> 
         </Style.Triggers> 
        </Style> 
       </ContentControl.Style> 
      </ContentControl> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

Часть XAML использует класс, называемый GridHelpers, который помогает в создании динамических строк и столбцов, вы можете получить исходный код от Rachael Lim's Blog.

Результат:

enter image description here

+0

Спасибо Марку. Я попытаюсь реализовать эту логику в кодировке и дам вам знать, если я это выясню. –

+0

@ Juniver Ханойский ответ обновлен. –

+1

Привет, Марк, я пробовал ваше решение с GridHelpers, и он работает хорошо. Я узнал об использовании GridHelpers и вашего Tuple. Большое спасибо. –

0

Это где Viewbox может быть использован, но он приходит с побочными эффектами.

Измените MinWidth на кнопке, чтобы получить соотношение Label to Button, что вам нравится, потому что дизайн будет страдать, когда окна сжимаются, но все равно, когда размер увеличивается.

Sample UI

Код

<Viewbox Stretch="Fill"> 
    <ItemsControl ItemsSource="{Binding HahaList}"> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <Grid> 
        <Grid.RowDefinitions> 
         <RowDefinition Height="Auto"/> 
         <RowDefinition/> 
        </Grid.RowDefinitions> 
        <Label Content="{Binding Name}"/> 
        <ItemsControl Grid.Row="1" 
          ItemsSource="{Binding ItemList}"> 
         <ItemsControl.ItemsPanel> 
          <ItemsPanelTemplate> 
           <UniformGrid Columns="5"/> 
          </ItemsPanelTemplate> 
         </ItemsControl.ItemsPanel> 
         <ItemsControl.ItemTemplate> 
          <DataTemplate> 
           <Button Content="{Binding Name}" MinWidth="75"/> 
          </DataTemplate> 
         </ItemsControl.ItemTemplate> 
        </ItemsControl> 
       </Grid> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <StackPanel/> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
    </ItemsControl> 
</Viewbox> 
+0

Благодарим вас за вашу идею. Использование 'ViewBox' является своего рода сложным способом, но все еще выполняет эту работу. Я узнал от вас использование «ViewBox». Однако он полностью искажает шрифт. Хаха спасибо. –