【问题标题】:Footer on ListView WPFListView WPF 上的页脚
【发布时间】:2019-03-01 03:27:07
【问题描述】:

我想在ListView 中添加一个页脚,并在其各自的列许可证和扫描中添加两列的总和,我发现了类似的内容 (Here),但如果我添加,页脚没有显示在 GridView 中添加 4 列,然后显示页脚行,但没有任何值。
GridViewColumnHeader 包含我也想应用于页脚的样式(我没有粘贴它以提供 Minimal , 功能示例)

这是预期的视图:

xaml

<Window x:Class="WpfApp2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp2"
        xmlns:system="clr-namespace:System;assembly=mscorlib"
        xmlns:utils="Helper"
        mc:Ignorable="d"
        Title="MainWindow"
        Height="450"
        Width="800">
    <Window.DataContext>
        <local:ViewModel />
    </Window.DataContext>
    <Window.Resources>
        <CollectionViewSource x:Key="ViewSource"
                              Source="{Binding DataList}">
            <CollectionViewSource.GroupDescriptions>
                <PropertyGroupDescription PropertyName="ToOrder" />
            </CollectionViewSource.GroupDescriptions>
        </CollectionViewSource>
    </Window.Resources>

    <Grid>
        <ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled"
                  ItemsSource="{Binding Source={StaticResource ViewSource}}">
            <ListView.GroupStyle>
                <GroupStyle>
                    <GroupStyle.ContainerStyle>
                        <Style TargetType="{x:Type GroupItem}">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type GroupItem}">
                                        <DockPanel>
                                            <Grid DockPanel.Dock="Bottom">
                                                <Grid.Resources>
                                                    <local:SumConverter x:Key="sumConverter" />
                                                </Grid.Resources>
                                                <Grid.RowDefinitions>
                                                    <RowDefinition/>
                                                    <RowDefinition/>
                                                </Grid.RowDefinitions>
                                                <Grid.ColumnDefinitions>
                                                    <ColumnDefinition Width="{Binding ElementName=Col1, Path=ActualWidth}"/>
                                                    <ColumnDefinition Width="{Binding ElementName=Col2, Path=ActualWidth}"/>
                                                    <ColumnDefinition Width="{Binding ElementName=Col3, Path=ActualWidth}"/>
                                                </Grid.ColumnDefinitions>
                                                <TextBlock Grid.Row="1"
                                                           Text="Sum: "
                                                           FontWeight="Bold" />
                                                <TextBlock Grid.Column="1"
                                                           Grid.Row="1"
                                                           Text="{Binding Path=Items, Converter={StaticResource sumConverter}, ConverterParameter=1}"/>
                                                <TextBlock Grid.Column="2"
                                                           Grid.Row="1"
                                                           Text="{Binding Path=Items, Converter={StaticResource sumConverter}, ConverterParameter=2}"/>
                                                <Line Grid.Column="0"
                                                      Grid.Row="0"
                                                      Grid.ColumnSpan="3"
                                                      Stroke="Black"
                                                      X2="500"
                                                      Fill="Black"
                                                      VerticalAlignment="Center" />
                                            </Grid>
                                            <ItemsPresenter />
                                        </DockPanel>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </GroupStyle.ContainerStyle>
                </GroupStyle>
            </ListView.GroupStyle>
            <ListView.View>
                <GridView x:Name="OverviewGridView">
                    <GridViewColumn DisplayMemberBinding="{Binding Date, StringFormat=dd.MM.yyyy}"
                                    Header="Date" 
                                    x:Name="Col1"/>
                    <GridViewColumn DisplayMemberBinding="{Binding LicenseCount}"
                                    Header="Licenses" 
                                    x:Name="Col2"/>
                    <GridViewColumn DisplayMemberBinding="{Binding ScansCount}"
                                    Header="Scans" 
                                    x:Name="Col3"/>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>

视图模型

namespace WpfApp2
{
    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using WpfApp2.Annotations;

    public class OverView
    {
        public int ToGroup { get; set; } = 1;
        public DateTime Date { get; set; }
        public int LicenseCount { get; set; }
        public int ScansCount { get; set; }
    }

    public class ViewModel : INotifyPropertyChanged
    {
        private int _totalLicenses;
        private ObservableCollection<OverView> _dataList;
        private int _totalScans;

        public ViewModel()
        {
            OverView a = new OverView
                             {
                                 Date = DateTime.Now.Subtract(new TimeSpan(1, 0, 0, 0)),
                                 LicenseCount = 2,
                                 ScansCount = 7
                             };
            OverView b = new OverView
                             {
                                 Date = DateTime.Now.Subtract(new TimeSpan(5, 0, 0, 0)),
                                 LicenseCount = 3,
                                 ScansCount = 2
                             };
            OverView c = new OverView { Date = DateTime.Now, LicenseCount = 5, ScansCount = 4 };
            OverView d = new OverView
                             {
                                 Date = DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0)),
                                 LicenseCount = 1,
                                 ScansCount = 3
                             };

            DataList = new ObservableCollection<OverView> { a, b, c, d };

            TotalLicenses = DataList.Sum(overview => overview.LicenseCount);
            TotalScans = DataList.Sum(overview => overview.ScansCount);
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public ObservableCollection<OverView> DataList
        {
            get => _dataList;
            set
            {
                _dataList = value;
                OnPropertyChanged();
            }
        }
        public int TotalLicenses
        {
            get => _totalLicenses;
            set
            {
                _totalLicenses = value;
                OnPropertyChanged();
            }
        }
        public int TotalScans
        {
            get => _totalScans;
            set
            {
                _totalScans = value;
                OnPropertyChanged();
            }
        }
        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

求和转换器

namespace WpfApp2
{
    #region Using

    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Windows.Data;

    #endregion

    public class SumConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            int sum = 0;
            if (value is IEnumerable<object> total)
            {
                foreach (object o in total)
                {
                    if (o is OverView overview)
                    {
                        int col = int.Parse((string)parameter);

                        sum += col == 1 ? overview.LicenseCount : overview.ScansCount;
                    }
                }

                return sum;
            }

            return 0;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => 1;
    }
}

提前致谢!

编辑,经过进一步测试,我成功地在 Overview 对象中创建了一个新属性以对其进行分组,然后使用转换器对我需要的列求和。 结果如下:代码随解决方案更新。

【问题讨论】:

  • 我不确定您在 ui 中显示信息的位置。您的意思是将总和作为一行添加到 Datalist 中吗?因为那没有发生。还是您的意思是将 ui 元素放在网格下方的 xaml 中以显示视图模型的总数?因为我也没有在 xaml 中看到这种情况。我错过了什么吗?
  • 正好是第二个,我需要在 GridView 下方显示另一行,其中包含 LicenseCount 和 ScanCount 列的总和
  • 我已更新我的问题以添加预期视图
  • 您是否考虑在您的 DataList 集合中添加一个“sum”项来显示列的总和?
  • 好的,我看到了更新。但是您的 Path 指向的 Columns 属性在哪里?

标签: c# wpf xaml mvvm


【解决方案1】:

你不能把它集成到列表视图中,但你可以像这样把它放在下面:

            <StackPanel>
                <GridViewRowPresenter DockPanel.Dock="Bottom"
                              Content="Sum"
                              Columns="{Binding ElementName=OverviewGridView, Path=Columns}">
                </GridViewRowPresenter>
                <ListView
                  HorizontalAlignment="Stretch"
                  ItemsSource="{Binding DataList}">
                    <ListView.View>
                        <GridView x:Name="OverviewGridView">
                            <GridViewColumn DisplayMemberBinding="{Binding Date}" Header="Date"/>
                            <GridViewColumn DisplayMemberBinding="{Binding LicenseCount}" Header="Licenses"/>
                            <GridViewColumn DisplayMemberBinding="{Binding ScansCount}" Header="Scans"/>
                        </GridView>
                    </ListView.View>
                </ListView>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="{Binding ElementName=OverviewGridView, Path=Columns[0].ActualWidth}"/>
                        <ColumnDefinition Width="{Binding ElementName=OverviewGridView, Path=Columns[1].ActualWidth}"/>
                        <ColumnDefinition Width="{Binding ElementName=OverviewGridView, Path=Columns[2].ActualWidth}"/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="Summe" Grid.Column="0" Margin="10,0"/>
                    <TextBlock Text="{Binding DataList, FallbackValue=0,Converter={StaticResource Summierer}, ConverterParameter=1}"  Margin="10,0" Grid.Column="1"/>
                    <TextBlock Text="{Binding DataList, FallbackValue=0,Converter={StaticResource Summierer}, ConverterParameter=2}"  Margin="10,0" Grid.Column="2"/>
                </Grid>
            </StackPanel>

这是我的转换器(需要重写!!我没有付出任何努力)

 public class SummUp: IValueConverter
{
    #region Convert
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var rtn = 0;
        var coll = (value as ObservableCollection<OverView>);
        var param = System.Convert.ToInt32(parameter);
        foreach (var item in coll)
        {
            if (param == 1)
            {
                rtn += item.LicenseCount;
            }
            else if (param == 2)
            {
                rtn += item.ScansCount;
            }
        }

        return rtn;
    }//END Convert
    #endregion Convert

    #region ConvertBack
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }//END ConvertBack 
    #endregion ConvertBack 

}//END class boolToNotVisibilityConverter : IValueConverter 

【讨论】:

  • 我之前考虑过这个问题,但我看到了这个stackoverflow.com/questions/1287979/…,这产生了我所要求的,用 Total 修复最后一行,但在那个例子中,他们只用一个来做价值,我相信这是我的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-08
  • 2013-07-24
  • 2014-07-07
  • 1970-01-01
  • 2012-01-01
  • 1970-01-01
相关资源
最近更新 更多