Сетка флажков в WPF - PullRequest
       21

Сетка флажков в WPF

5 голосов
/ 20 декабря 2010

У меня есть текст данных WPF UserControl, связанный с таким классом:

public class CheckBoxGridViewModel
{
  public List<List<bool>> Checkboxes {get; set;}
}

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

Этот вопрос , кажется, отвечает на мой, за исключением того, что ответ не дал примера, и я не могу понять, как его написать.

Итак, вопрос в том, как мне написать xaml для отображения флажков свойства Checkboxes, чтобы они выстроились в красивую сетку?

Внешний список будет каждой строкой, а внутренний список - каждым столбцом строки.

Ответы [ 4 ]

3 голосов
/ 21 декабря 2010

Не ясно, ожидаете ли вы, что каждый внутренний список будет одинакового размера, но если они есть, вы можете использовать простую настройку.Использование вложенных ItemsControls с одной строкой / столбцом UniformGrids обеспечит вам равномерное распределение и автоматически обрабатывает коллекции любого размера без необходимости настраивать определения строк и столбцов, такие как Grid:

<ItemsControl ItemsSource="{Binding Checkboxes}">
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <ItemsControl ItemsSource="{Binding}">
        <ItemsControl.ItemTemplate>
          <DataTemplate>
            <CheckBox IsChecked="{Binding}"/>
          </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsPanelTemplate>
          <UniformGrid Rows="1"/>
        </ItemsPanelTemplate>
      </ItemsControl>
    </DataTemplate>
  </ItemsControl.ItemTemplate>
  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <UniformGrid Columns="1"/>
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>
</ItemsControl>
2 голосов
/ 21 декабря 2010

Вы можете создать класс, который предоставляет свойства Row, Column и Value, и связать их с коллекцией.Это позволяет назначать позиции строк и столбцов, используя метод по вашему выбору, а расположение в сетке очень просто (если вы, конечно, понимаете, как ItemsControl использует его свойства ItemsPanel и ItemContainerStyle):

      <ItemsControl ItemsSource="{Binding Checkboxes}">
        <ItemsControl.ItemTemplate>
          <DataTemplate>
            <CheckBox IsChecked="{Binding Value, Mode=TwoWay}"/>
          </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.ItemsPanel>
          <ItemsPanelTemplate>
          <Grid DockPanel.Dock="Top">
            <Grid.ColumnDefinitions>
              <ColumnDefinition Width="20"/>
              <ColumnDefinition Width="20"/>
              <ColumnDefinition Width="20"/>
              <ColumnDefinition Width="20"/>
              <ColumnDefinition Width="20"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
              <RowDefinition Height="20"/>
              <RowDefinition Height="20"/>
              <RowDefinition Height="20"/>
              <RowDefinition Height="20"/>
              <RowDefinition Height="20"/>
              <RowDefinition Height="20"/>
            </Grid.RowDefinitions> 
            </Grid>
          </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemContainerStyle>
          <Style TargetType="ContentPresenter">
            <Setter Property="Grid.Row" Value="{Binding Row}"/>
            <Setter Property="Grid.Column" Value="{Binding Column}"/>
          </Style>
        </ItemsControl.ItemContainerStyle>
      </ItemsControl>
2 голосов
/ 20 декабря 2010

См. этот вопрос .Ответ от Jobi Joy позволит вам представить 2D-список, но Binding не будет работать, поэтому вы не сможете редактировать свои значения.

Чтобы иметь возможность связывать значения, вы можете использовать вспомогательный класс, подобный этому

public static class BindableListHelper
{
    public static List<List<Ref<T>>> GetBindable2DList<T>(List<List<T>> list)
    {
        List<List<Ref<T>>> refInts = new List<List<Ref<T>>>();

        for (int i = 0; i < list.Count; i++)
        {
            refInts.Add(new List<Ref<T>>());
            for (int j = 0; j < list[i].Count; j++)
            {
                int a = i;
                int b = j;
                refInts[i].Add(new Ref<T>(() => list[a][b], z => { list[a][b] = z; }));
            }
        }
        return refInts;
    }
}

Этот метод использует этот класс Ref

public class Ref<T> 
{
    private readonly Func<T> getter; 
    private readonly Action<T> setter;
    public Ref(Func<T> getter, Action<T> setter) 
    { 
        this.getter = getter; 
        this.setter = setter; 
    }
    public T Value { get { return getter(); } set { setter(value); } } 
}

Затем вы можете установить ItemsSourceдля ItemsControl с

itemsControl.ItemsSource = BindableListHelper.GetBindable2DList<bool>(Checkboxes);

и редактирование должно работать

Используя тот же код, что и Jobi Joy из вопроса, который я связал, вы можете изменить Button в DataTemplate_Level2вместо CheckBox и связать IsChecked для него вместо Value (поскольку в противном случае он будет указывать на класс Ref)

<Window.Resources>
    <DataTemplate x:Key="DataTemplate_Level2">
        <CheckBox IsChecked="{Binding Path=Value}" Height="15" Width="15" Margin="2"/>
    </DataTemplate>
    <DataTemplate x:Key="DataTemplate_Level1">
        <ItemsControl ItemsSource="{Binding}" ItemTemplate="{DynamicResource DataTemplate_Level2}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
    </DataTemplate>
</Window.Resources>
<StackPanel>
    <Border HorizontalAlignment="Left" BorderBrush="Black" BorderThickness="2">
        <ItemsControl x:Name="itemsControl" ItemTemplate="{DynamicResource DataTemplate_Level1}"/>
    </Border>
</StackPanel>

Без установки свойства Content для CheckBox он будет выглядеть примерно так

alt text

0 голосов
/ 20 декабря 2010

Как именно вы хотите организовать эту сетку?Это будет влиять на то, какие ItemsControl.ItemsPanel использовать.Пара идей ...

Используйте UniformGrid или WPF Toolkit WrapPanel.

...