自适应触发器和数据模板

Posted

技术标签:

【中文标题】自适应触发器和数据模板【英文标题】:AdaptiveTrigger and DataTemplate 【发布时间】:2015-11-12 08:09:18 【问题描述】:

AdaptiveTrigger 可以在 DataTemplate 中工作吗?

这是我用来自定义 ShellNavigation 的代码,除了视觉状态外,它工作正常。他们不会触发任何事情。

<shell:ShellHeadView x:Key="ShellHeadView_01">
    <shell:ShellHeadView.ContentTemplate>
        <DataTemplate>
            <Grid Margin="20,0">
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup>
                        <VisualState x:Name="GreenBackgroundVisualState">
                            <VisualState.Setters>
                                <Setter Target="headViewLeft.Background" Value="Green" />
                            </VisualState.Setters>
                            <VisualState.StateTriggers>
                                <AdaptiveTrigger MinWindowWidth="1000"/>
                            </VisualState.StateTriggers>
                        </VisualState>
                        <VisualState x:Name="OrangeBackgroundVisualState">
                            <VisualState.Setters>
                                <Setter Target="headViewLeft.Background" Value="Orange" />
                            </VisualState.Setters>
                            <VisualState.StateTriggers>
                                <AdaptiveTrigger MinWindowWidth="2000"/>
                            </VisualState.StateTriggers>
                        </VisualState>
                        <VisualState x:Name="RedBackgroundVisualState">
                            <VisualState.Setters>
                                <Setter Target="headViewLeft.Background" Value="Red" />
                            </VisualState.Setters>
                            <VisualState.StateTriggers>
                                <AdaptiveTrigger MinWindowWidth="3000"/>
                            </VisualState.StateTriggers>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <Grid Grid.Column="0" x:Name="headViewLeft" Width="100" Height="90">

                </Grid>

【问题讨论】:

【参考方案1】:

尝试像这样将您的 DataTemplate 包裹在 UserControl 中 -

<DataTemplate>
    <UserControl>
        <Grid>
            <VisualStateManager.VisualStateGroups>
            ...
        </Grid>
    </UserControl>
</DataTemplate>

看起来任何具有Content 属性的Control 都可以工作。这就是 UserControl 有效的原因,ContentControl 也是如此。

因此,如果您将 UserControl 替换为 ContentControl 并给它一个空的 Style。它也应该可以工作。

<Style x:Key="EmptyContentControlStyle" TargetType="ContentControl">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ContentControl" />
        </Setter.Value>
    </Setter>
</Style>

<DataTemplate>
    <ContentControl Style="StaticResource EmptyContentControlStyle">
        <Grid>
            <VisualStateManager.VisualStateGroups>
            ...
        </Grid>
    </ContentControl>
</DataTemplate>

【讨论】:

如何使用它来使动态创建的列表项工作?ListView listView = new ListView(); listView.ItemsSource = source.Articles; listView.Template = ???; listView.IsItemClickEnabled = true; listView.ItemClick += OpenArticle_ItemClick; listView.SelectionMode = ListViewSelectionMode.None; FWIW,UserControl 效果很好,但ContentControl 不行。仍然是一个很好的答案! @EricLiprandi 嗯,你给你的 ContentControl 一个空样式了吗? 我错过了那部分:) - 我想UserControl 对我来说更干净......我想不出在这种情况下UserControlContentControl 之间的功能差异。 这里是另一个answer,用于处理ListViewDataTemplate 中的状态。【参考方案2】:

创建两个数据模板。使用自适应触发器更改您的ItemsControl 上的ItemTemplate

TBH 将自适应触发器放在通用模板中而不是页面视图中对我来说有点奇怪。

一般来说,我强烈建议不要将用户控件放在数据模板中,如另一个答案中所建议的那样。用户控件很慢,因此将它们放在模板中反复使用可能会降低性能(带有控件模板的自定义控件是更好的选择)。

您还可以创建一个在模板之间切换的自定义控件。示例:

public class AdaptiveControl : ContentControl

    public AdaptiveControl()
    
        SizeChanged += AdaptiveControl_SizeChanged;
    

    private void AdaptiveControl_SizeChanged(object sender, SizeChangedEventArgs e)
    
        Update();
    
    private void Update() 
    
        if (ActualWidth < Size)
            ContentTemplate = SmallTemplate;
        else
            ContentTemplate = LargeTemplate;
    

    public double Size
    
        get  return (double)GetValue(SizeProperty); 
        set  SetValue(SizeProperty, value); 
    

    public static readonly DependencyProperty SizeProperty =
        DependencyProperty.Register(nameof(Size), typeof(double), typeof(AdaptiveControl), new PropertyMetadata(200d, (s, e) => ((AdaptiveControl)s).Update()));

    public DataTemplate SmallTemplate
    
        get  return (DataTemplate)GetValue(SmallTemplateProperty); 
        set  SetValue(SmallTemplateProperty, value); 
    

    public static readonly DependencyProperty SmallTemplateProperty =
        DependencyProperty.Register(nameof(SmallTemplate), typeof(DataTemplate), typeof(AdaptiveControl), new PropertyMetadata(null, (s, e) => ((AdaptiveControl)s).Update()));


    public DataTemplate LargeTemplate
    
        get  return (DataTemplate)GetValue(LargeTemplateProperty); 
        set  SetValue(LargeTemplateProperty, value); 
    

    public static readonly DependencyProperty LargeTemplateProperty =
        DependencyProperty.Register(nameof(LargeTemplate), typeof(DataTemplate), typeof(AdaptiveControl), new PropertyMetadata(null, (s, e) => ((AdaptiveControl)s).Update()));


【讨论】:

以上是关于自适应触发器和数据模板的主要内容,如果未能解决你的问题,请参考以下文章

适当的自适应卡片输入.ChoiceSet 模板结构

如何在自适应卡片模板中使用 $when 来找出传入数据有效负载的长度并删除输入块

视觉工作室混合自适应触发按钮丢失?

苹果cms V10模板 自适应黄白模板

Visual Blend 2015 未显示编辑自适应触发器

12.1.0.2自适应特性导致SQL性能下降