ListView DataTemplate绑定

时间:2010-10-25 19:37:30

标签: wpf wpf-controls binding

我有以下ListView:

    <ListView Name="listView">
            <ListView.View>
                <GridView>
                    <GridView.ColumnHeaderContainerStyle>
                        <Style TargetType="{x:Type GridViewColumnHeader}">
                            <Setter Property="Visibility"
                                    Value="Collapsed"/>
                        </Style>
                    </GridView.ColumnHeaderContainerStyle>
                    <GridViewColumn>
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <StackPanel>
                                    <CheckBox
                                          Margin="0"
                                          VerticalAlignment="Center"
                                          IsChecked="{Binding IsChecked}"
                                          Visibility="{Binding IsChecked, Converter={StaticResource boolToVis}}">
                                    </CheckBox>
                                </StackPanel>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn>
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Margin="0"
                                           Text="{Binding Text}"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                </GridView>
            </ListView.View>
        </ListView>

ListView中的项目属于以下类型:

public class CheckBoxListViewItemSource : INotifyPropertyChanged
{
    public CheckBoxListViewItemSource(String text)
    {
        m_text = text;
    }

    public bool IsChecked
    {
        get { return m_checked; }
        set
        {
            if (m_checked == value) return;
            m_checked = value;
            RaisePropertyChanged("IsChecked");
        }
    }

    public String Text
    {
        get { return m_text; }
        set
        {
            if (m_text == value) return;
            m_text = value;
            RaisePropertyChanged("Text");
        }
    }

    public override string ToString()
    {
        return Text;
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged(string propName)
    {
        PropertyChangedEventHandler eh = PropertyChanged;
        if (eh != null)
        {
            eh(this, new PropertyChangedEventArgs(propName));
        }
    }

    private bool m_checked;
    private String m_text;
}

ListView中复选框的可见性绑定到ListViewItem的IsChecked值。转换器是一个简单的bool to visibility转换器:

public class BoolToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter,
                          CultureInfo culture)
    {
        if (value is Boolean)
        {
            return ((bool)value) ? Visibility.Visible : Visibility.Collapsed;
        }

        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter,
                              CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

在ListView后面的代码我有:

    void listView_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        foreach (var item in e.RemovedItems)
        {
            CheckBoxListViewItemSource source = item as CheckBoxListViewItemSource;
            source.IsChecked = false;
        }
        foreach (var item in e.AddedItems)
        {
            CheckBoxListViewItemSource source = item as CheckBoxListViewItemSource;
            source.IsChecked = true;
        }
    }

复选框可见性的绑定对我不起作用。默认的IsChecked值为false,因此列表显示时没有复选框。如果我选择了一个项目,则不会出现该复选框。

但是,如果我将IsChecked的默认值设置为true,则所有列表项都会显示一个复选框,如果我选择一个项目然后取消选中它,则复选框会正确消失。

我想要实现的是,所有项目都从没有复选框开始,选择项目显示已选中复选框,取消选择项目会隐藏复选框。

我出错的任何想法?

2 个答案:

答案 0 :(得分:1)

手动将第一个GridViewColumn的宽度设置为固定值。似乎ListView将它的宽度设置为零,如果它什么都不包含,并且当复选框开始出现时不会更新宽度。

或者,更改BoolToVisibilityConverter的代码以返回Visibility.Hidden而不是Visibility.Collapsed。

答案 1 :(得分:1)

我知道这已经得到了回答,但我使用以下方法解决了这个问题:

 <GridViewColumn Header="MyColumn">
       <GridViewColumn.CellTemplate>
              <DataTemplate>
                    <ContentPresenter Content="{Binding MyItem, UpdateSourceTrigger=PropertyChanged}" ContentTemplate="{StaticResource myTemplate}"/>
              </DataTemplate>
         </GridViewColumn.CellTemplate>
 </GridViewColumn>

在Window中我有一个为MyItem类型定义的DataTemplate:

<Window.Resources>
        <DataTemplate DataType="{x:Type myViewModels:MyItemViewModel}" x:Key="myTemplate" >
           ...template code
        </DataTemplate>
</Window.Resources>