DataTrigger не срабатывает при прокрутке в ListView

У нас возникла проблема с парой элементов управления ListView в WPF, эти элементы управления связаны вместе, чтобы работать как единая сетка с закрепленным столбцом с правой стороны, который содержит флажок. Это сделано для того, чтобы левый раздел можно было прокручивать, а правый флажок всегда оставался на экране.

У нас также есть ряд триггеров данных, которые необходимы для установки визуального состояния в пользовательском стиле списка. Это используется для выделения цвета фона выбранных строк (у нас также есть стиль выбранного элемента).

Мы решили использовать триггеры данных для срабатывания визуальных состояний, а не устанавливать цвет фона строки, поскольку это не дает нам необходимого контроля над дизайном.

Проблема, с которой мы сталкиваемся в настоящее время, связана с прокруткой ListView, когда он содержит большое количество строк; мы полагаем, что это приводит к тому, что элемент управления перерисовывает содержимое, однако тогда он, похоже, не запускает триггеры данных, устанавливающие соответствующие визуальные состояния для каждой строки.

Два контроллера 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>

Чтобы запустить триггеры данных, нам пришлось установить их в шаблоне ячейки GridViewColumn, это может быть частью проблемы, однако, если мы поместим их где-нибудь еще, они не будут реагировать.

Это копия стиля, используемого для элементов списка; есть левый и правый вариант этого стиля, однако их содержание практически идентично.

<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 используется для управления триггерами данных и является частью приведенного ниже кода.

    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
    }

В настоящее время мы в тупике..... Помогите :)


person Spongeali    schedule 17.05.2013    source источник


Ответы (1)


Единственный способ, который мы смогли найти для решения этой проблемы, — это использовать следующий оператор в обоих представлениях списка. Я считаю, что это устанавливает физическую прокрутку содержимого, а не логическую прокрутку, и, следовательно, не вызывает перерисовку (я уверен, что кто-то может меня поправить :)).

ScrollViewer.CanContentScroll="False"

Он должен быть установлен в обоих списках, иначе вы можете столкнуться с очень странным поведением в списках.

person Spongeali    schedule 21.05.2013