2010-12-20 20 views
5

我有一個WPF UserControl的DataContext的與類是這樣的:電網在WPF

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

我希望它顯示一個複選框網格。我假設我可以使用ItemsControl,但不知道如何使用每行的動態一組列。

This question似乎回答我的,除非答案沒有給出的例子,我不知道如何寫出來。

所以問題是,我該如何編寫xaml來顯示覆選框屬性的複選框,以便它們排列在一個漂亮的網格中?

外部列表將是每一行,內部列表將是該行的每一列。

+0

有人試圖編寫一個井字? :D – David 2010-12-21 11:05:12

回答

2

請參閱this question。 Jobi Joy的答案會讓你展示2D列表,但綁定不起作用,所以你不能編輯你的值。

爲了能夠綁定值,您可以使用一個輔助類這樣

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

此方法使用該參考類

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

和編輯應該工作

使用相同的代碼苡樂從我掛的問題,您可以在DataTemplate_Level2改變按鈕,一個複選框並綁定器isChecked爲它而不是值(因爲它會指向參考類其他)

<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屬性的複選框,它會是這個樣子

alt text

0

安排該網格如何你到底想要什麼?這將影響使用哪個ItemsControl.ItemsPanel。一些想法...

使用UniformGrid或WPF工具包WrapPanel。

+0

看到編輯的問題,感謝您的幫助 – Jose 2010-12-20 15:34:05

2

您可能會考慮創建一個顯示,ColumnValue屬性的類,並綁定到這些類的集合。這使您可以使用您選擇的方法分配行和列的位置和佈局在網格非常簡單(一旦你瞭解如何ItemsControl使用其ItemsPanelItemContainerStyle性能,當然):

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

目前尚不清楚如果您希望每個內部列表的大小相同,但如果它們是可以使用簡單的設置。使用嵌套ItemsControls單行/列UniformGrids會給你一個均勻分佈,並自動處理各種規模的集合,而無需設置行和列定義像格:

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

+1,這是一個比我的回答更好的呈現方式。 – 2010-12-21 08:31:35

+0

感謝這個答案,它幫了我很多!有一個錯誤,您在中缺少,並導致異常:-) – Mischo5500 2015-11-14 09:44:40