Vista风格ListView(GridViewRowPresenter)

时间:2015-02-02 09:45:14

标签: c# wpf listview

我想在ListView中显示不同行(不同风格和不同内容)的数据。但是一旦我尝试应用一种风格(假设什么都不改变),选择就会停止工作,而且它不再是Vista style

我做错了什么?也许是错误的做法?

<ListView ItemsSource="{Binding A}">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="B" DisplayMemberBinding="{Binding B}"/>
            ...
        </GridView>
    </ListView.View>

    <!-- commenting below block will return Vista style back -->
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListViewItem">
                        <GridViewRowPresenter Content="{TemplateBinding Content}"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ListView.ItemContainerStyle>
</ListView>

2 个答案:

答案 0 :(得分:2)

如果您希望在ControlTemplate中显示不同行(不同风格和不同内容)的数据,则不应更改ListViewItem的{​​{1}}。

请改用ListView。您可以根据绑定的数据类型设置行的样式。

假设你有一个这样的视图模型:

DataTemplate

然后,只需为要在列表视图中显示的项目定义public class ViewModel : INotifyPropertyChanged { public List<object> A { get; private set; } public ViewModel() { this.A = new List<object> { Brushes.BlueViolet, 42, false }; } }

DataTemplate

使用这种方法,您将获得代表您的数据的列表视图行,保留核心<ListView ItemsSource="{Binding A}"> <ListView.View> <GridView> <GridViewColumn Header="B"/> </GridView> </ListView.View> <ListView.Resources> <DataTemplate DataType="{x:Type media:Brush}"> <Rectangle Width="25" Height="25" Fill="{Binding Mode=OneWay}"/> </DataTemplate> <DataTemplate DataType="{x:Type sys:Boolean}"> <CheckBox IsChecked="{Binding Mode=OneWay}"/> </DataTemplate> <DataTemplate DataType="{x:Type sys:Int32}"> <TextBlock Text="{Binding Mode=OneWay}"> <TextBlock.Style> <Style TargetType="{x:Type TextBlock}"> <Setter Property="FontWeight" Value="Bold"/> </Style> </TextBlock.Style> </TextBlock> </DataTemplate> </ListView.Resources> </ListView> 功能和“Vista样式”。

List view

答案 1 :(得分:1)

我尽量保持它尽可能通用,所以我为每行可以采用的不同类型定义一个简单的枚举:

public enum RowType { Bool, Int32 }

现在我在行的视图模型中使用它:

public class Row: DependencyObject
{
    //create a new row with the given value
    //automatically set Value, Info and RowType based on the param
    public Row(object val)
    {
        Value = val;
        if (val.GetType() == typeof(bool)) RowType = WpfApplication3.RowType.Bool;
        else RowType = WpfApplication3.RowType.Int32;
        Info = val.ToString() + " of type " +val.GetType().ToString();
    }

    public RowType RowType { get; set; }

    /// <summary>
    /// Gets or sets a bindable value that indicates Value
    /// </summary>
    public object Value
    {
        get { return (object)GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }
    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value", typeof(object), typeof(Row), new PropertyMetadata(0));

    /// <summary>
    /// Gets or sets a bindable value that indicates Info
    /// </summary>
    public string Info
    {
        get { return (string)GetValue(InfoProperty); }
        set { SetValue(InfoProperty, value); }
    }
    public static readonly DependencyProperty InfoProperty =
        DependencyProperty.Register("Info", typeof(string), typeof(Row), new PropertyMetadata(""));
}

现在视图模型已准备就绪,我创建了一个简单的TemplateSelector,它响应给定行的RowType:

public class Selector : DataTemplateSelector
{
    //Template for RowType==Bool
    public DataTemplate Template1 { get; set; }
    //Template for RowType==Int32
    public DataTemplate Template2 { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        var row = item as Row;
        if (row == null) return null;

        switch (row.RowType)
        {
            case RowType.Bool:
                return Template1;
            case RowType.Int32:
                return Template2;
            default:
                return null;
        }
    }
}

我在Xaml中使用它像这样:

<Window.Resources>

    <!-- selects CellTemplate for column1 (Value) based on RowType -->
    <local:Selector x:Key="valueSelector">
        <local:Selector.Template1>
            <DataTemplate>
                <CheckBox IsChecked="{Binding Value, Mode=OneWay}"/>
            </DataTemplate>
        </local:Selector.Template1>
        <local:Selector.Template2>
            <DataTemplate>
                <TextBlock Text="{Binding Value, Mode=OneWay}">
                    <TextBlock.Style>
                        <Style TargetType="{x:Type TextBlock}">
                            <Setter Property="FontWeight" Value="Bold"/>
                        </Style>
                    </TextBlock.Style>
                </TextBlock>
            </DataTemplate>
        </local:Selector.Template2>
    </local:Selector>

    <!-- selects CellTemplate for column2 (Info) based on RowType -->
    <local:Selector x:Key="infoSelector">
        <local:Selector.Template1>
            <DataTemplate>
                <Canvas Height="16">
                    <TextBlock Text="{Binding Info, Mode=OneWay}" 
                               Foreground="Blue" VerticalAlignment="Top"/>
                </Canvas>
            </DataTemplate>
        </local:Selector.Template1>
        <local:Selector.Template2>
            <DataTemplate>
                <Canvas Height="16">
                    <TextBlock Text="{Binding Info, Mode=OneWay}"
                               VerticalAlignment="Top"/>
                </Canvas>
            </DataTemplate>
        </local:Selector.Template2>
    </local:Selector>
</Window.Resources>

<ListView ItemsSource="{Binding A}">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Value" 
                 CellTemplateSelector="{StaticResource valueSelector}"/>
            <GridViewColumn Header="Info" Width="0"
                 CellTemplateSelector="{StaticResource infoSelector}"/>
        </GridView>
    </ListView.View>
</ListView>

结果如下:

enter image description here

并非我根据dymanoid的答案写了这个答案,答案是基于给定的信息准确的。