如何在数据模板之间共享一组通用的VisualState?

时间:2019-01-24 02:59:51

标签: c# xaml uwp datatemplate visualstates

我有一个UWP UserControl,用于显示分组的项目(带标签的),可以通过单击标签头将其展开,但也支持未标记的项目。 (类似于TreeView,其中每个项目可能在节点内也可能不在节点内)。

因此输出可能看起来像这样-标签行可以折叠或展开,并且未标记的项目显示在已标记的项目下方:

白皮书

–白皮书1.pdf

–白皮书2.pdf

技术规范

–技术规范1.doc

–技术规范2.doc

DocumentWithNoTag1.pdf

DocumentWithNoTag2.doc

该控件使用模板选择器来选择要显示的两种类型的内容之一(TaggedItemTemplate或UntaggedItemTemplate数据模板),但是我需要一组通用的VisualStateManger状态,我可以使用这两种模板从下面的代码中设置其状态。任何项目都被选中。因此,在选择绑定项目时,我需要显示可视状态“ FolderVisualState”或“ FileVisualState”。

问题是,当我运行它并转到将可视状态设置为的代码(在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>

这是背后的代码。如果单击了文件夹级别(节点)项或FileVisualState项是实际文件,则状态选择应显示FolderVisualState。

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);
        }
    }
}

我猜这是某种名称空间问题,其中XAML中的VisualState不知道如何访问正确的DataTemplate。我已经用谷歌搜索,但没有找到解决此类问题的任何答案...有人可以建议如何解决此问题吗?

0 个答案:

没有答案