C# wpf 列表视图为网格视图中的每一列提供单独的滚动条

本文关键字:视图 一列 滚动条 单独 列表 wpf 网格 | 更新日期: 2023-09-27 18:31:29

我希望每列都有单独的滚动条

<ListView ItemsSource="{Binding}">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Name" 
                            DisplayMemberBinding="{Binding name}"/>
            <GridViewColumn Header="Price"  
                            DisplayMemberBinding="{Binding price}"/>
        </GridView>
    </ListView.View>
</ListView>

我想每列有 2 个水平滚动条(名称和价格),我的目的地是设置带有图片的列,但我想在图片变大时滚动该图片。

C# wpf 列表视图为网格视图中的每一列提供单独的滚动条

我找到了一种基于此解决方案仅在网格视图底部添加滚动的方法:如何在 WPF 列表视图 ( 网格视图 ) 中创建组页脚 。它看起来有点笨拙,但似乎还没有解决方案。我在 xaml 中所做的是将组描述绑定到一个假属性,以便只显示一次页脚。

XAML:

  <PropertyGroupDescription PropertyName="fake" />

然后我修改了一个页脚模板,使其显示滚动条:

<Style TargetType="{x:Type GroupItem}">
                                <Setter Property="Template">
                                    <Setter.Value>
                                        <ControlTemplate TargetType="{x:Type GroupItem}">
                                            <DockPanel>
                                                <Grid DockPanel.Dock="Bottom" >
                                                    <Grid.ColumnDefinitions>
                                                        <ColumnDefinition Width="{Binding ElementName=first, Path=Width, UpdateSourceTrigger=PropertyChanged}" />
                                                        <ColumnDefinition Width="{Binding ElementName=second, Path=Width, UpdateSourceTrigger=PropertyChanged}" />
                                                    </Grid.ColumnDefinitions>
                                                    <ScrollBar Grid.Column="0" Orientation="Horizontal" Scroll="ScrollBar1_Scroll"
                                                          Width="{Binding ElementName=first, Path=Width, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" >
                                                    </ScrollBar>
                                                    <ScrollBar Grid.Column="1" Orientation="Horizontal" Scroll="ScrollBar2_Scroll"
                                                               Width="{Binding ElementName=second, Path=Width, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"/>
                                                </Grid>
                                                <ItemsPresenter />
                                            </DockPanel>
                                        </ControlTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Style>
有很多

绑定是调整带有列的滚动条大小所必需的。那里的另一个技巧:您必须首先为每个GridViewColumn设置Width,否则滚动条只会在您手动调整列大小后出现。我移动单元格的内容Margin改变StackPanelCellTemplate的属性。下面是整个代码,我认为这不是一个完整的工作解决方案,但是一个很好的起点。

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
    <Grid>
        <Grid.Resources>
            <CollectionViewSource x:Key="ViewSource" Source="{Binding Path=Collection, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource Mode=FindAncestor,
            AncestorType=Window} }">
                <CollectionViewSource.GroupDescriptions>
                    <PropertyGroupDescription PropertyName="fake" />
                </CollectionViewSource.GroupDescriptions>
            </CollectionViewSource>
        </Grid.Resources>
        <HeaderedItemsControl  Header="ListView">
            <StackPanel>
                <ListView  ItemsSource="{Binding Source={StaticResource ViewSource}, UpdateSourceTrigger=PropertyChanged}" x:Name="Lv" Margin="5,5,5,5">
                    <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.ColumnDefinitions>
                                                            <ColumnDefinition Width="{Binding ElementName=first, Path=Width, UpdateSourceTrigger=PropertyChanged}" />
                                                            <ColumnDefinition Width="{Binding ElementName=second, Path=Width, UpdateSourceTrigger=PropertyChanged}" />
                                                        </Grid.ColumnDefinitions>
                                                        <ScrollBar Grid.Column="0" Orientation="Horizontal" Scroll="ScrollBar1_Scroll"
                                                              Width="{Binding ElementName=first, Path=Width, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" >
                                                        </ScrollBar>
                                                        <ScrollBar Grid.Column="1" Orientation="Horizontal" Scroll="ScrollBar2_Scroll"
                                                                   Width="{Binding ElementName=second, Path=Width, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"/>
                                                    </Grid>
                                                    <ItemsPresenter />
                                                </DockPanel>
                                            </ControlTemplate>
                                        </Setter.Value>
                                    </Setter>
                                </Style>
                            </GroupStyle.ContainerStyle>
                        </GroupStyle>
                    </ListView.GroupStyle>
                    <ListView.View >
                <GridView >
                            <GridViewColumn Header="Name"  x:Name="first" Width="50">
                                <GridViewColumn.CellTemplate>
                                    <DataTemplate>
                                        <StackPanel Margin="{Binding Path=Offset1, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource Mode=FindAncestor,
            AncestorType=Window} }">
                                            <TextBlock x:Name="tb1"  Text="{Binding name}"></TextBlock>
                                        </StackPanel>
                                    </DataTemplate>
                                </GridViewColumn.CellTemplate>
                            </GridViewColumn>
                            <GridViewColumn Header="Price" x:Name="second"  Width="50">
                                <GridViewColumn.CellTemplate>
                                    <DataTemplate>
                                            <StackPanel Margin="{Binding Path=Offset2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource Mode=FindAncestor,
            AncestorType=Window} }" >
                                                <TextBlock Text="{Binding price}"></TextBlock>
                                            </StackPanel>
                                    </DataTemplate>
                                </GridViewColumn.CellTemplate>
                            </GridViewColumn>
                        </GridView>
            </ListView.View>           
        </ListView>
            </StackPanel>
        </HeaderedItemsControl>
    </Grid>
</Window>

和代码隐藏

using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls.Primitives;
namespace WpfApplication1
{
    public partial class MainWindow:INotifyPropertyChanged
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        private List<MyItem> _collection = new List<MyItem>();
        public List<MyItem> Collection 
        { 
            get { return _collection; }
            set { _collection = value; InvokePropertyChanged(new PropertyChangedEventArgs("Collection")); }
        }
        private Thickness _offset1;
        public Thickness Offset1
        {
            get { return _offset1; }
            set { _offset1 = value; InvokePropertyChanged(new PropertyChangedEventArgs("Offset1")); }
        }
        private Thickness _offset2;
        public Thickness Offset2
        {
            get { return _offset2; }
            set { _offset2 = value; InvokePropertyChanged(new PropertyChangedEventArgs("Offset2")); }
        }
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            Collection.Add(new MyItem("item1", "10"));
            Collection.Add(new MyItem("item2", "200"));
            Collection.Add(new MyItem("item3", "600000"));
            Collection.Add(new MyItem("item4", "1"));
        }
        private void ScrollBar1_Scroll(object sender, ScrollEventArgs e)
        {
            //imitate scrolling here
            double leftToRight = Offset1.Left;
            if (e.ScrollEventType == ScrollEventType.SmallIncrement)
                leftToRight += 5;
            if (e.ScrollEventType == ScrollEventType.SmallDecrement)
                leftToRight -= 5;
            Offset1 = new Thickness(leftToRight, 0, 0, 0);
        }
        private void ScrollBar2_Scroll(object sender, ScrollEventArgs e)
        {
            //imitate scrolling here
            double leftToRight = Offset2.Left;
            if (e.ScrollEventType == ScrollEventType.SmallIncrement)
                leftToRight += 5;
            if (e.ScrollEventType == ScrollEventType.SmallDecrement)
                leftToRight -= 5;
            Offset2 = new Thickness(leftToRight, 0, 0, 0);
        }
        public event PropertyChangedEventHandler PropertyChanged;
        public void InvokePropertyChanged(PropertyChangedEventArgs e)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, e);
        }
    }
    public class MyItem
    {
        public string name { get; set; }
        public string price { get; set; }
        public MyItem(string  n, string p)
        {
            name = n;
            price = p;
        }
    }
}