WinRT XAML - 如何在列表视图中设置选定项目的样式?

时间:2017-03-02 15:09:14

标签: c# xaml windows-runtime

在我的WinRT应用程序中,我想显示状态值列表并突出显示当前状态。当列表显示时,它应该是只读的,因此不与用户交互。虽然我使用ListView,但我希望禁用任何选择功能。我认为禁用ListView可以解决这个问题。 但是现在在我的代码背后,我有;

  public IList<JobStatusItem> StatusList
    {
        get
        {
            var values = Enum.GetValues(typeof(JobStatus));
            var selected = Status.ToString();
            var i = 0;
            var list = new List<JobStatusItem>();
            foreach (var value in values)
            {
                i++;
                var item = GetStatusDisplay(value.ToString());
                list.Add(new JobStatusItem
                {
                    Id = i,
                    Status = item,
                    Selected = value.ToString().Equals(selected)
                });                    
            }

            return list;
        }
    }

对于我的XAML,我有

                <ListView x:Name="ListStatus" 
                          IsItemClickEnabled="False" 
                          IsSwipeEnabled="False"
                          SelectionMode="Single" 
                          ItemsSource="{Binding Path=AssignedJobs.SelectedDay.SelectedJob.StatusList, Mode=OneWay}"
                          >
                    <ListView.ItemContainerStyle>
                        <Style TargetType="ListViewItem">
                            <Setter Property="IsSelected" Value="{Binding Path=Selected, Mode=OneWay}"/>
                        </Style>
                    </ListView.ItemContainerStyle>

                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Path=Status}"></TextBlock>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>

当我运行此选项时,所选状态的样式不会被选中。为什么会这样,我该如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

代码中的绑定表达式(<Setter Property="IsSelected" Value="{Binding Path=Selected, Mode=OneWay}"/>)不会起作用,因为上下文不在项目级别。

由于WinRT中缺少祖先绑定,因此很难使用纯绑定来实现您想要的效果;但是,在后面的代码中检查 IsSelected属性非常简单。在一天结束时,如果您想要一个纯XAML解决方案,您始终可以将下面的代码包装在Behavior内。

您基本上想要订阅ListView的{​​{3}}事件,并手动设置IsSelected的{​​{1}}属性以匹配ItemContainer属性你的模型Selected。像这样的东西 -

JobStatusItem

另一种可能的解决方案

由于您需要包含突出显示选项的只读列表,因此最好通过将 private void OnListViewContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args) { if (args.ItemContainer != null && !args.InRecycleQueue && args.Phase == 0) { args.ItemContainer.IsSelected = ((JobStatusItem)args.Item).Selected; 设置为ListView来完全禁用SelectionMode上的任何点击/点按互动}。

然后在None内,用DataTemplate包裹TextBlock,并在Border属性时为Border提供不同的BackgroundSelected

答案 1 :(得分:1)

因此,我希望您希望禁用手动选择,同时维护程序化选择。列表视图中的项目。

实现您要执行的操作的最简单方法是将ListView定义为SelectionMode="Single",并将SelectedItem属性绑定到ViewModel的相应属性。要阻止任何手动交互,只需在IsHittestVisible="True"上放置一个网格即可阻止任何手动交互。如下所示:

<Grid>
    <ListView x:Name="ListStatus"
              SelectionMode="Single"
              ItemsSource="{Binding StatusList}"
              SelectedItem="{Binding SelectedItem}" 
              ItemTemplate="{StaticResource UnselectedListDataTemplate}"/>
    <Grid IsHitTestVisible="True" Background="Transparent" />
</Grid>

我会选择完全不同的方法

您尝试实现的更方便的方法是设置ListView.SelectionMode="None"并使用ItemTemplateSelectorItemContainerStyleSelector来切换突出显示版本和普通版本之间的模板/样式。

public class JobStatusItemTemplateSelector : DataTemplateSelector
{
    public DataTemplate SelectedTemplate { get; set; }
    public DataTemplate UnselectedTemplate { get; set; }
    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
    {
        var element = item as JobStatusItem;
        if (element == null) return UnselectedTemplate;
        return element.Selected ? SelectedTemplate : UnselectedTemplate;
    }
}

将ListView定义为:

<Page.Resources>
    <DataTemplate 
        x:DataType="local:JobStatusItem"
        x:Key="SelectedListDataTemplate">
        <TextBlock Text="{Binding Status}" FontWeight="ExtraBold" Foreground="DarkOrchid"/>
    </DataTemplate>
    <DataTemplate 
        x:DataType="local:JobStatusItem"
        x:Key="UnselectedListDataTemplate">
        <TextBlock Text="{Binding Status}" />
    </DataTemplate>
    <local:JobStatusItemTemplateSelector x:Key="ListTemplateSelector" 
                                         SelectedTemplate="{StaticResource SelectedListDataTemplate}" 
                                         UnselectedTemplate="{StaticResource UnselectedListDataTemplate}"/>
</Page.Resources>

<ListView x:Name="ListStatus"
          SelectionMode="None"
          ItemsSource="{Binding StatusList}"
          ItemTemplateSelector="{StaticResource ListTemplateSelector}">
</ListView>

这样,您就可以轻松区分已发生,正在进行且将来会发生的状态步骤,甚至可以让您轻松整合过去时发生的错误等步骤。 根据您使用的是TemplateSelectorStyleSelector,您甚至可以通过不同的模板实现符号,图片等。