質問

enter image description hereI need to display a table showing the available categories an item can fall into and a count for how many records are in each category for the current data context.

The category names will be in a static class enum for simplicity, then I will be able to look up in my result set by category name (string) to determine the count.

I attach my XAML I am using to style the table how I want, but I cant help but think there must be a more elegant way. Does anyone have any pointers?

<SolidColorBrush x:Key="SubTableHeading" Color="#BAA6BA" />
<SolidColorBrush x:Key="SubTableHeaderText" Color="#FFFFFF" />
<SolidColorBrush x:Key="SubTableText" Color="#888888" />
<SolidColorBrush x:Key="SubTableRow" Color="#FFFCFF" />
<SolidColorBrush x:Key="SubTableAlternateRow" Color="#FAEEFF" />
<SolidColorBrush x:Key="SubTableHighlightCell" Color="#EADEEF" />

<Grid Grid.Row="0" Grid.Column="1" Grid.RowSpan="7" Background="{StaticResource SubTableHeading}">
        <Grid.RowDefinitions>
            <RowDefinition Height="18" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <TextBlock Grid.Column="0" Text="Category breakdown" Padding="5,2,5,2" Foreground="{StaticResource SubTableHeaderText}" />
        <Grid Grid.Row="1" Background="{StaticResource SubTableRow}" >
            <Grid.RowDefinitions>
                <RowDefinition Height="13" />
                <RowDefinition Height="13" />
                <RowDefinition Height="13" />
                <RowDefinition Height="13" />
                <RowDefinition Height="13" />
                <RowDefinition Height="13" />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="5" />
                <ColumnDefinition Width="105" />
                <ColumnDefinition Width="25" />
                <ColumnDefinition Width="10" />
                <ColumnDefinition Width="105" />
                <ColumnDefinition Width="25" />
                <ColumnDefinition Width="10" />
                <ColumnDefinition Width="110" />
                <ColumnDefinition Width="25" />
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Column="1" Grid.Row="0" Foreground="{StaticResource SubTableText}">Category name</TextBlock>
            <TextBlock Grid.Column="1" Grid.Row="1" Foreground="{StaticResource SubTableText}">Category name</TextBlock>
            <TextBlock Grid.Column="1" Grid.Row="2" Foreground="{StaticResource SubTableText}">Category name</TextBlock>
            <TextBlock Grid.Column="1" Grid.Row="3" Foreground="{StaticResource SubTableText}">Category name</TextBlock>
            <TextBlock Grid.Column="1" Grid.Row="4" Foreground="{StaticResource SubTableText}">Category name</TextBlock>
            <TextBlock Grid.Column="1" Grid.Row="5" Foreground="{StaticResource SubTableText}">Category name</TextBlock>
            <TextBlock Grid.Column="2" Grid.Row="0" Width="25" Background="{StaticResource SubTableHighlightCell}" Foreground="{StaticResource SubTableText}" TextAlignment="Center">1</TextBlock>
            <TextBlock Grid.Column="2" Grid.Row="1" Width="25" Background="{StaticResource SubTableHighlightCell}" Foreground="{StaticResource SubTableText}" TextAlignment="Center">1</TextBlock>
            <TextBlock Grid.Column="2" Grid.Row="2" Width="25" Background="{StaticResource SubTableHighlightCell}" Foreground="{StaticResource SubTableText}" TextAlignment="Center">1</TextBlock>
            <TextBlock Grid.Column="2" Grid.Row="3" Width="25" Background="{StaticResource SubTableHighlightCell}" Foreground="{StaticResource SubTableText}" TextAlignment="Center">1</TextBlock>
            <TextBlock Grid.Column="2" Grid.Row="4" Width="25" Background="{StaticResource SubTableHighlightCell}" Foreground="{StaticResource SubTableText}" TextAlignment="Center">1</TextBlock>
            <TextBlock Grid.Column="2" Grid.Row="5" Width="25" Background="{StaticResource SubTableHighlightCell}" Foreground="{StaticResource SubTableText}" TextAlignment="Center">1</TextBlock>
            <TextBlock Grid.Column="4" Grid.Row="0" Foreground="{StaticResource SubTableText}">Category name</TextBlock>
            <TextBlock Grid.Column="4" Grid.Row="1" Foreground="{StaticResource SubTableText}">Category name</TextBlock>
            <TextBlock Grid.Column="4" Grid.Row="2" Foreground="{StaticResource SubTableText}">Category name</TextBlock>
            <TextBlock Grid.Column="4" Grid.Row="3" Foreground="{StaticResource SubTableText}">Category name</TextBlock>
            <TextBlock Grid.Column="4" Grid.Row="4" Foreground="{StaticResource SubTableText}">Category name</TextBlock>
            <TextBlock Grid.Column="4" Grid.Row="5" Foreground="{StaticResource SubTableText}">Category name</TextBlock>
            <TextBlock Grid.Column="5" Grid.Row="0" Width="25" Background="{StaticResource SubTableHighlightCell}" Foreground="{StaticResource SubTableText}" TextAlignment="Center">1</TextBlock>
            <TextBlock Grid.Column="5" Grid.Row="1" Width="25" Background="{StaticResource SubTableHighlightCell}" Foreground="{StaticResource SubTableText}" TextAlignment="Center">1</TextBlock>
            <TextBlock Grid.Column="5" Grid.Row="2" Width="25" Background="{StaticResource SubTableHighlightCell}" Foreground="{StaticResource SubTableText}" TextAlignment="Center">1</TextBlock>
            <TextBlock Grid.Column="5" Grid.Row="3" Width="25" Background="{StaticResource SubTableHighlightCell}" Foreground="{StaticResource SubTableText}" TextAlignment="Center">1</TextBlock>
            <TextBlock Grid.Column="5" Grid.Row="4" Width="25" Background="{StaticResource SubTableHighlightCell}" Foreground="{StaticResource SubTableText}" TextAlignment="Center">1</TextBlock>
            <TextBlock Grid.Column="5" Grid.Row="5" Width="25" Background="{StaticResource SubTableHighlightCell}" Foreground="{StaticResource SubTableText}" TextAlignment="Center">1</TextBlock>
            <TextBlock Grid.Column="7" Grid.Row="0" Foreground="{StaticResource SubTableText}">Category name</TextBlock>
            <TextBlock Grid.Column="7" Grid.Row="1" Foreground="{StaticResource SubTableText}">Category name</TextBlock>
            <TextBlock Grid.Column="7" Grid.Row="2" Foreground="{StaticResource SubTableText}">Category name</TextBlock>
            <TextBlock Grid.Column="7" Grid.Row="3" Foreground="{StaticResource SubTableText}">Category name</TextBlock>
            <TextBlock Grid.Column="7" Grid.Row="4" Foreground="{StaticResource SubTableText}">Category name</TextBlock>
            <TextBlock Grid.Column="7" Grid.Row="5" Foreground="{StaticResource SubTableText}">Category name</TextBlock>
            <TextBlock Grid.Column="8" Grid.Row="0" Width="25" Background="{StaticResource SubTableHighlightCell}" Foreground="{StaticResource SubTableText}" TextAlignment="Center">1</TextBlock>
            <TextBlock Grid.Column="8" Grid.Row="1" Width="25" Background="{StaticResource SubTableHighlightCell}" Foreground="{StaticResource SubTableText}" TextAlignment="Center">1</TextBlock>
            <TextBlock Grid.Column="8" Grid.Row="2" Width="25" Background="{StaticResource SubTableHighlightCell}" Foreground="{StaticResource SubTableText}" TextAlignment="Center">1</TextBlock>
            <TextBlock Grid.Column="8" Grid.Row="3" Width="25" Background="{StaticResource SubTableHighlightCell}" Foreground="{StaticResource SubTableText}" TextAlignment="Center">1</TextBlock>
            <TextBlock Grid.Column="8" Grid.Row="4" Width="25" Background="{StaticResource SubTableHighlightCell}" Foreground="{StaticResource SubTableText}" TextAlignment="Center">1</TextBlock>
            <TextBlock Grid.Column="8" Grid.Row="5" Width="25" Background="{StaticResource SubTableHighlightCell}" Foreground="{StaticResource SubTableText}" TextAlignment="Center">1</TextBlock>
        </Grid>
    </Grid>
役に立ちましたか?

解決

You can change your layout to use an ItemsControl. Here's a prototype (without your styling)...

    <ItemsControl ItemsSource="{Binding MyCollection}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel Orientation="Horizontal" MaxWidth="450"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal" MaxWidth="150">
                    <TextBlock Width="90" Text="{Binding CategoryName}" Margin="0,0,10,0"/>
                    <TextBlock Width="50" Text="{Binding CategoryCount}"/>
                </StackPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

This items control uses a horizontal Wrap Panel so that your categories are wrapped across the surface and will start a new row when the allotted space is exhausted on the current row.

The item template has two bound text blocks which can be used to display your items. The control itself is bound to a collection of your category counts.

The container class would look like this...

public class CategoryCounts: INotifyPropertyChanged
{
    private int _categoryCount;
    public int CategoryCount
    {
        [DebuggerStepThrough]
        get { return _categoryCount; }
        [DebuggerStepThrough]
        set
        {
            if (value != _categoryCount)
            {
                _categoryCount = value;
                OnPropertyChanged("CategoryCount");
            }
        }
    }
    private string _categoryName;
    public string CategoryName
    {
        [DebuggerStepThrough]
        get { return _categoryName; }
        [DebuggerStepThrough]
        set
        {
            if (value != _categoryName)
            {
                _categoryName = value;
                OnPropertyChanged("CategoryName");
            }
        }
    }
}

Finally, the View Model would look something like this...

public class ViewModel:INotifyPropertyChanged
{
    public ObservableCollection<CategoryCounts> MyCollection { get; set; }
    public ViewModel()
    {
        MyCollection = new ObservableCollection<CategoryCounts>();
        MyCollection.Add(new CategoryCounts{CategoryName = "some category", CategoryCount = 22});
    }
    #region INotifyPropertyChanged Implementation
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string name)
    {
        var handler = System.Threading.Interlocked.CompareExchange(ref PropertyChanged, null, null);
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
    #endregion
}

You can get almost the same results using a DataGrid or a ListView, but the 'wrapping' effect will be forfeit because grids use a 'record per row' extending in the vertical direction, laid out with proper column headers etc.

他のヒント

  1. for layout use ItemControl with ItemTemlate.
  2. for styling (Foreground, Background) use Style.
  3. for padding\margin use the style setting instead of unnecessary columns.

Instead of creating a table yourself using a grid and lots of manually placed text boxes, you could just use a tool that was made for this: A ListView with its View set to a GridView.

If you have a view model for these categories, you can easily bind to them. It would look like this in XAML. Here Categories is some property in your data context which is a list to items which themselves have a Name and a Number property which you bind to in the GridViewColumn definitions. Any styling can also be made using the GridViewColumn, or if you need something more special, you can provide a custom CellTemplate.

<ListView ItemsSource="{Binding Categories}">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Category" DisplayMemberBinding="{Binding Name}" />
            <GridViewColumn Header="Number" DisplayMemberBinding="{Binding Number}" />
        </GridView>
    </ListView.View>
</ListView>
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top