Как разделить общий набор визуальных состояний между шаблонами данных? - PullRequest
0 голосов
/ 24 января 2019

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

Таким образом, выходные данные могут выглядеть следующим образом - строка тега может быть свернута или развернута, а под тегами отображаются элементы без метки:

Белая бумага

- Белая бумага 1.pdf

- Техническая документация 2.pdf

Технические характеристики

- Технические характеристики 1.doc

- Технические характеристики 2.doc

DocumentWithNoTag1.pdf

DocumentWithNoTag2.doc

Элемент управления использует селектор шаблонов для выбора одного из двух типов содержимого для отображения (шаблоны данных TaggedItemTemplate или UntaggedItemTemplate), но мне нужен общий набор VisualStateMangerсостояния, которые я могу использовать для любого шаблона, чтобы установить его состояние из кода, когда выбран любой элемент.Итак, при выборе связанного элемента мне нужно либо отобразить визуальное состояние «FolderVisualState» или «FileVisualState».

Проблема заключается в том, что я запускаю его и получаю код, в котором он устанавливает визуальное состояние для переходаto (в OnMiscItemPropertyChanged) я получаю сообщение об ошибке:

"System.Runtime.InteropServices.COMException:« Не обнаружены установленные компоненты. Целевой объект с именем «FolderExpander» не может быть разрешен для Setter. ».

Вот мой UserControl:

<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="using:Athena.UWP.Components"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:Controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
             xmlns:components="using:Athena.UWP.Components"
             xmlns:models="using:Athena.UWP.Models"
             xmlns:Converters="using:Template10.Converters"
             xmlns:primitives="using:Telerik.UI.Xaml.Controls.Primitives"
             xmlns:data="using:Telerik.UI.Xaml.Controls.Data"
             x:Class="Athena.UWP.Components.MiscItemView"
             mc:Ignorable="d"
             d:DesignHeight="300"
             d:DesignWidth="400">

    <UserControl.Resources>

        <Converters:StringFormatConverter x:Key="StringFormatConverter" />

        <DataTemplate x:Key="SubItemDataTemplate"
                      x:DataType="models:BoardMiscItem">

            <components:MiscItemView MiscItem="{x:Bind Mode=OneWay}"
                                     ItemSelected="OnSubItemSelected" />

        </DataTemplate>

        <Thickness x:Key="ButtonContentItemMargin">0,0,8,0</Thickness>

        <DataTemplate x:Key="FileButtonTemplate"
                      x:DataType="models:BoardMiscItem">

            <Button x:Name="FileButton"
                    HorizontalAlignment="Stretch"
                    VerticalAlignment="Stretch"
                    Visibility="Collapsed"
                    Click="OnItemClicked"
                    HorizontalContentAlignment="Stretch">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition />
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="70" />
                    </Grid.ColumnDefinitions>
                    <Border CornerRadius="45"
                            Height="10"
                            Width="10"
                            Margin="{StaticResource ButtonContentItemMargin}">
                        <Border.Background>
                            <SolidColorBrush Color="{x:Bind StateColour, Mode=OneWay}" />
                        </Border.Background>
                    </Border>
                    <TextBlock TextWrapping="Wrap"
                               Text="{x:Bind DisplayName, Mode=OneWay}"
                               Grid.Column="1"
                               Margin="{StaticResource ButtonContentItemMargin}" />
                    <TextBlock Text="{x:Bind UpdateDate, Converter={StaticResource StringFormatConverter}, ConverterParameter=\{0:dd MMM yyyy\}, Mode=OneWay}"
                               Grid.Column="2"
                               Margin="{StaticResource ButtonContentItemMargin}" />
                    <TextBlock Text="{x:Bind Type, Mode=OneWay}"
                               Grid.Column="4"
                               TextTrimming="CharacterEllipsis"
                               ToolTipService.ToolTip="{x:Bind Type, Mode=OneWay}" />
                </Grid>
            </Button>
        </DataTemplate>

        <DataTemplate x:Key="TaggedItemTemplate" x:DataType="models:BoardMiscItem">

            <Grid>
                <Button Content="FileButtonTemplate" DataContext="{Binding}"/>
                <Controls:Expander x:Name="FolderExpander"
                                   Header="{Binding MiscItem.Tag, Mode=OneWay}"
                                   Visibility="Collapsed"
                                   HorizontalContentAlignment="Stretch">
                    <ListView ItemsSource="{Binding SubItems, Mode=OneWay}"
                              HorizontalContentAlignment="Stretch"
                              ScrollViewer.VerticalScrollBarVisibility="Disabled"
                              ItemTemplate="{StaticResource SubItemDataTemplate}"
                              ItemContainerStyle="{StaticResource StretchListViewItemStyle}"
                              SelectionMode="None" />
                </Controls:Expander>
            </Grid>
        </DataTemplate>

        <DataTemplate x:Key="UntaggedItemTemplate" x:DataType="models:BoardMiscItem">
            <Button Content="FileButtonTemplate" DataContext="{Binding}"/>
        </DataTemplate>

        <components:MiscItemTemplateSelector x:Key="MiscItemTemplateSelector"
                                             ExpanderTemplate="{StaticResource TaggedItemTemplate}"
                                             NormalTemplate="{StaticResource UntaggedItemTemplate}" />

    </UserControl.Resources>

    <Grid>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="MiscItemStateGroup">
                <VisualState x:Name="NoVisualState" />
                <VisualState x:Name="FileVisualState">
                    <VisualState.Setters>
                        <Setter Target="FileButton.(UIElement.Visibility)" Value="Visible" />
                    </VisualState.Setters>
                </VisualState>
                <VisualState x:Name="FolderVisualState">
                    <VisualState.Setters>
                        <Setter Target="FolderExpander.(UIElement.Visibility)" Value="Visible" />
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

        <ContentPresenter Content="{Binding MiscItem}"
                            ContentTemplateSelector="{StaticResource MiscItemTemplateSelector}"/>
    </Grid>

</UserControl>

Вот код позади.Выбор состояния должен показывать FolderVisualState, если щелкнуть элемент уровня (узла) папки или FileVisualState - это элемент фактического файла.

namespace MyApp.UWP.Components
{
    public sealed partial class MiscItemView : UserControl
    {
        public DataTemplate NormalTemplate { get; set; }
        public DataTemplate ExpanderTemplate { get; set; }

        public MiscItemView()
        {
            this.InitializeComponent();
        }

        public static readonly DependencyProperty MiscItemProperty =
            DependencyProperty.Register(nameof(MiscItem), typeof(BoardMiscItem), typeof(MiscItemView), 
                                        new PropertyMetadata(null, OnMiscItemPropertyChanged));

        public BoardMiscItem MiscItem
        {
            get
            {
                return (BoardMiscItem)GetValue(MiscItemProperty);
            }
            set
            {
                SetValue(MiscItemProperty, value);
            }
        }

        private static void OnMiscItemPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var view = d as MiscItemView;

            BoardMiscItem miscItem = (BoardMiscItem)e.NewValue;
            if (miscItem == null)
            {
                VisualStateManager.GoToState(view, nameof(NoVisualState), true);
            }
            else if (miscItem.SubItems.Any())
            {
                VisualStateManager.GoToState(view, nameof(FolderVisualState), true);
            }
            else
            {
                VisualStateManager.GoToState(view, nameof(FileVisualState), true);
            }
        }

        public event RoutedEventHandler ItemSelected;

        private void OnSubItemSelected(object sender, RoutedEventArgs e)
        {
            ItemSelected?.Invoke(sender, e);
        }

        private void OnItemClicked(object sender, RoutedEventArgs e)
        {
            ItemSelected?.Invoke(MiscItem, e);
        }
    }
}

Я полагаю, что это какая-то проблема пространства имен, когда VisualStates вXAML не знает, как получить доступ к правильному шаблону данных.Я погуглил, но не нашел ответа на этот вопрос ... Кто-нибудь может подсказать, как это исправить?

...