简体   繁体   中英

AdaptiveTrigger and DataTemplate

Will AdaptiveTrigger work in a DataTemplate?

That's my code i'm using to customize my ShellNavigation, it is working fine except the visual states. They will not trigger anything.

<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>

Try wrapping your DataTemplate inside a UserControl like this -

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

Looks like any Control that has got a Content property will work. That's why UserControl works, so does a ContentControl .

So if you replace the UserControl with a ContentControl and give it an empty Style . It should work too.

<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>

Create two data templates. Use the adaptive trigger to change the ItemTemplate on your ItemsControl

TBH it feels a bit weird to me to put adaptive triggers inside a generic template, rather than in the page view.

In general I would heavily recommend against putting user controls inside datatemplates as is suggested in another answer. User controls are SLOW, so having them in templates that are used over and over again can be bad for performance (custom controls with control templates are a better alternative for that).

You could also create a custom control that switches between templates. Example:

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

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM