ListView滚动时,DataTrigger不触发

4
我们在WPF中遇到了一对ListView控件的问题,这些控件链接在一起,以形成一个带有右侧冻结列(包含复选框)的单个网格。这样左侧部分将是可滚动的,但右侧的复选框将始终保持在屏幕上。
我们还有许多DataTrigger,这些触发器需要设置自定义ListView样式中的视觉状态。这用于突出显示所选行的背景颜色(我们还有所选项样式)。
我们选择使用DataTrigger来触发视觉状态,而不是设置行的背景颜色,因为这不能给我们所需的对设计的控制。
我们目前遇到的问题与当ListView包含大量行时滚动相关;我们认为这会导致控件重新绘制内容,然后似乎没有触发Datatrigger来设置每行的相关视觉状态。
两个ListView控件。
<StackPanel Name="dataGridProjects" Orientation="Horizontal" Height="300">
    <ListView Name="listView1" ItemsSource="{Binding List}" Width="700" ScrollViewer.VerticalScrollBarVisibility="Hidden" 
        ScrollViewer.ScrollChanged="listView1ScrollChanged" SelectedItem="{Binding ListSelected}" BorderThickness="0" >

        <ListView.View>
            <GridView>
                <!-- This column is used to fire the visual states and is hidden -->
                <GridViewColumn Header="" Width="0">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Grid>
                                <i:Interaction.Triggers>
                                    <ie:DataTrigger Binding ="{Binding VisualItemState}" Value="0">
                                        <ie:GoToStateAction StateName="ItemUnselected" TargetObject="{Binding ElementName=ItemRootGrid}" UseTransitions="False" ></ie:GoToStateAction>
                                    </ie:DataTrigger>
                                    <ie:DataTrigger Binding ="{Binding VisualItemState}" Value="1">
                                        <ie:GoToStateAction StateName="ItemSelected" TargetObject="{Binding ElementName=ItemRootGrid}" UseTransitions="False" ></ie:GoToStateAction>
                                    </ie:DataTrigger>
                                    <ie:DataTrigger Binding ="{Binding VisualItemState}" Value="2">
                                        <ie:GoToStateAction StateName="ItemCompleted" TargetObject="{Binding ElementName=ItemRootGrid}" UseTransitions="False" ></ie:GoToStateAction>
                                    </ie:DataTrigger>
                                    <ie:DataTrigger Binding ="{Binding VisualItemState}" Value="3">
                                        <ie:GoToStateAction StateName="ItemHasConflicts" TargetObject="{Binding ElementName=ItemRootGrid}" UseTransitions="False" ></ie:GoToStateAction>
                                    </ie:DataTrigger>
                                </i:Interaction.Triggers>
                            </Grid>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>

                <GridViewColumn DisplayMemberBinding="{Binding ProjName}" >
                    <GridViewColumn.HeaderTemplate>
                        <DataTemplate>
                            <TextBlock Name="txtProjName" Text="{Binding DescProjectReference}" MinWidth="150" />
                        </DataTemplate>
                    </GridViewColumn.HeaderTemplate>
                </GridViewColumn>
                <GridViewColumn DisplayMemberBinding="{Binding VisualItemState}" >
                    <GridViewColumn.HeaderTemplate>
                        <DataTemplate>
                            <TextBlock Name="txtVisState" Text="VisualItemState" MinWidth="150"/>
                        </DataTemplate>
                    </GridViewColumn.HeaderTemplate>
                </GridViewColumn>
                <GridViewColumn DisplayMemberBinding="{Binding ItemState}" >
                    <GridViewColumn.HeaderTemplate>
                        <DataTemplate>
                            <TextBlock Name="txtItemState" Text="ItemState" MinWidth="150"/>
                        </DataTemplate>
                    </GridViewColumn.HeaderTemplate>
                </GridViewColumn>
                <GridViewColumn DisplayMemberBinding="{Binding IsSelected}" >
                    <GridViewColumn.HeaderTemplate>
                        <DataTemplate>
                            <TextBlock Name="txtIsSelected" Text="IsSelected" MinWidth="250"/>
                        </DataTemplate>
                    </GridViewColumn.HeaderTemplate>
                </GridViewColumn>

            </GridView>
        </ListView.View>
        <ListView.ItemContainerStyle>

            <Style TargetType="ListViewItem" BasedOn="{StaticResource ExtendedListViewItemLeft}">
                <Setter Property="IsEnabled" Value="{Binding Path=ProjectSyncRecord.IsEnabled, Mode=TwoWay}"/>
            </Style>

        </ListView.ItemContainerStyle>

    </ListView>

    <ListView Name="listView2" ItemsSource="{Binding List}" ScrollViewer.ScrollChanged="listView2ScrollChanged" SelectedItem="{Binding ListSelected}" BorderThickness="0" >
        <ListView.View>
            <GridView>
                <GridViewColumn Header="IsSelected" >
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Grid>
                                <!-- Triggers for the visual states -->
                                <i:Interaction.Triggers>
                                    <ie:DataTrigger Binding ="{Binding Path=VisualItemState}" Value="0">
                                        <ie:GoToStateAction StateName="ItemUnselected" TargetObject="{Binding ElementName=ItemRootGrid}" UseTransitions="False" ></ie:GoToStateAction>
                                    </ie:DataTrigger>
                                    <ie:DataTrigger Binding ="{Binding Path=VisualItemState}" Value="1">
                                        <ie:GoToStateAction StateName="ItemSelected" TargetObject="{Binding ElementName=ItemRootGrid}" UseTransitions="False" ></ie:GoToStateAction>
                                    </ie:DataTrigger>
                                    <ie:DataTrigger Binding ="{Binding Path=VisualItemState}" Value="2">
                                        <ie:GoToStateAction StateName="ItemCompleted" TargetObject="{Binding ElementName=ItemRootGrid}" UseTransitions="False" ></ie:GoToStateAction>
                                    </ie:DataTrigger>
                                    <ie:DataTrigger Binding ="{Binding Path=VisualItemState}" Value="3">
                                        <ie:GoToStateAction StateName="ItemHasConflicts" TargetObject="{Binding ElementName=ItemRootGrid}" UseTransitions="False" ></ie:GoToStateAction>
                                    </ie:DataTrigger>
                                </i:Interaction.Triggers>

                                <CheckBox IsChecked="{Binding Path=IsSelected, Mode=TwoWay}" IsEnabled="{Binding Path=ProjectSyncRecord.IsEnabled}" MinWidth="100"/>
                            </Grid>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>

                </GridViewColumn>

            </GridView>
        </ListView.View>
        <ListView.ItemContainerStyle>

            <Style TargetType="ListViewItem" BasedOn="{StaticResource ExtendedListViewItemRight}">
                <Setter Property="IsEnabled" Value="{Binding Path=ProjectSyncRecord.IsEnabled, Mode=TwoWay}"/>
            </Style>

        </ListView.ItemContainerStyle>
    </ListView>

</StackPanel>

为了触发datatriggers,我们需要在GridViewColumn的celltemplate中设置它们,这可能是问题的一部分,但如果我们将它们放在其他任何地方,它们都不会响应。
这是用于listview项目的样式副本;有左侧和右侧版本的样式,但它们的内容几乎相同。
<Style x:Key="ExtendedListViewItemLeft" TargetType="ListViewItem">
    <Setter Property="Padding" Value="5"/>
    <Setter Property="HorizontalContentAlignment" Value="Left"/>
    <Setter Property="VerticalContentAlignment" Value="Top"/>
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="FontSize" Value="12" />
    <Setter Property="MinHeight" Value="25" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListBoxItem">
                <Grid x:Name="ItemRootGrid" Background="{TemplateBinding Background}">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal"/>
                            <VisualState x:Name="MouseOver">
                                <Storyboard>
                                    <DoubleAnimation Duration="0" To=".35" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="fillColor"/>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Disabled">
                                <Storyboard>
                                    <DoubleAnimation Duration="0" To=".55" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="contentPresenter"/>
                                    <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="fillColorDisabled"/>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                        <VisualStateGroup x:Name="SelectionStates">
                            <VisualState x:Name="Unselected"/>
                            <VisualState x:Name="Selected">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="FocusVisualElement">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <Visibility>Visible</Visibility>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                        <VisualStateGroup x:Name="FocusStates">
                            <VisualState x:Name="Focused" />
                            <VisualState x:Name="Unfocused"/>
                        </VisualStateGroup>
                        <VisualStateGroup Name="SelectedStates">
                            <VisualState x:Name="ItemSelected">
                                <Storyboard>
                                    <DoubleAnimation Duration="00:00:00.25" To=".75" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="fillColorSelected"/>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="ItemUnselected">
                                <Storyboard>
                                    <DoubleAnimation Duration="00:00:00.25" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="fillColorSelected"/>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>

                    <Border x:Name="fillColor" Background="#FFBADDE9" IsHitTestVisible="False" Opacity="00" CornerRadius="10,0,0,10" Margin="2,2,0,2"/>
                    <Border x:Name="fillColor2" Background="#FFBADDE9" IsHitTestVisible="False" Opacity="0" CornerRadius="10,0,0,10" Margin="2,2,0,2"/>
                    <Border x:Name="fillColorSelected" Background="#FFBADDE9" IsHitTestVisible="False" Opacity="0" CornerRadius="10,0,0,10" Margin="2,2,0,2"/>
                    <Border x:Name="fillColorDisabled" Background="LightGray" IsHitTestVisible="False" Opacity="0" CornerRadius="10,0,0,10" Margin="2,2,0,2"/>

                    <GridViewRowPresenter x:Name="contentPresenter" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="{TemplateBinding Padding}" />

                    <Border x:Name="FocusVisualElement" BorderBrush="#FF6DBDD1" BorderThickness="1" CornerRadius="10,0,0,10" Margin="2,2,0,2" Visibility="Collapsed"/>
                    <!--<Rectangle x:Name="FocusVisualElement" RadiusY="4" RadiusX="4" Margin="2" Stroke="#FF6DBDD1" StrokeThickness="1" Visibility="Collapsed"/>-->

                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

背后的视图模型持有一个ObservableCollection,它绑定了两个ListView控件。这个集合保存了项目的许多详细信息,但是所有这些信息都能够成功地进行绑定。VisualItemState被用来控制datatriggers,并且是以下代码的一部分。

    public class SyncObject : NotificationObject
    {
        #region Fields

        /// <summary>
        /// Is the option selected.
        /// </summary>
        private bool isSelected;

        /// <summary>
        /// The project sync record.
        /// </summary>
        private ProjectSync projectSyncRecord;

        /// <summary>
        /// Set the state for the UI 
        /// </summary>
        private ItemState visualItemState;

        #endregion Fields

        #region Properties

        /// <summary>
        /// Gets or sets a value indicating whether IsSelected.
        /// </summary>
        public bool IsSelected
        {
            get
            {
                return this.isSelected;
            }

            set
            {
                this.isSelected = value;

                this.VisualItemState = value ? ItemState.Selected : ItemState.Unselected;

                this.RaisePropertyChanged(() => this.IsSelected);
            }
        }

        /// <summary>
        /// Gets or sets ProjectSyncRecord.
        /// </summary>
        public ProjectSync ProjectSyncRecord
        {
            get
            {
                return this.projectSyncRecord;
            }

            set
            {
                this.projectSyncRecord = value;
                this.RaisePropertyChanged(() => this.ProjectSyncRecord);
            }
        }

        /// <summary>
        /// Gets or sets VisualItemState.
        /// </summary>
        public ItemState VisualItemState
        {
            get
            {
                return this.visualItemState;
            }

            set
            {
                this.visualItemState = value;
                this.RaisePropertyChanged(() => this.VisualItemState);
            }
        }

        public string ProjName { get; set; }

        #endregion Properties
    }

我们目前遇到了一些困难..... 帮帮忙 :)

1个回答

2

我们找到解决此问题的唯一方法是在两个列表视图上都使用以下语句。我相信这将内容设置为物理滚动,而不是逻辑滚动,因此不会引起重绘(我相信有人可能会纠正我 :) )。

ScrollViewer.CanContentScroll="False"

必须在两个列表视图上设置它,否则您可能会在列表视图之间遇到一些非常奇怪的行为。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接