How do I reuse VisualState, VisualStateGroup, and VsualStateManager in a share?

I have created many buttons that use the same VisualStateManager, VisualStateGroup and VisualState in my Windows Phone project. Then I want to reuse them as shared resources as another type of item, like margin, colors, etc.

But I only found a way to reuse the storyboard so it would be better if I can reuse the entire VisualState.

Is there a reusable VisualState solution?

+3


source to share


1 answer


The solution I found, I tested in Windows 10 UWP app, I tested several options like XAML deserialization, cloning, etc., but I eventually found the following solution to be the best:

1 - Set VisualStateGroup as resource

 <Application.Resources>
   <DataTemplate x:Key="VisualStateTemplate">
    <Grid>
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup >
            <VisualState x:Name="NarrowView" >
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="0" />
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="Text.(RelativePanel.Below)" Value="Image" />
                    <Setter Target="Content.(RelativePanel.Below)" Value="Text" />
                </VisualState.Setters>
            </VisualState>
            <VisualState x:Name="WideView">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="860" />
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="Text.(RelativePanel.RightOf)" Value="Image" />
                    <Setter Target="Content.(RelativePanel.Below)" Value="Image" />
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
  </Grid>
 </DataTemplate>
</Application.Resources>

      

This is the first trick you can use to "load" VisualStateGroup

multiple times.

2 - Implement an attached property to set the control that is VisualStateGroup



public class VisualStateExtensions : DependencyObject
{
    public static void SetVisualStatefromTemplate(UIElement element, DataTemplate value)
    {
        element.SetValue(VisualStatefromTemplateProperty, value);
    }

    public static DataTemplate GetVisualStatefromTemplate(UIElement element)
    {
        return (DataTemplate) element.GetValue(VisualStatefromTemplateProperty);
    }

    public static readonly DependencyProperty VisualStatefromTemplateProperty = DependencyProperty.RegisterAttached("VisualStatefromTemplate", typeof(DataTemplate), typeof(VisualStateExtensions), new PropertyMetadata(null, VisualStatefromTemplateChanged));

    private static void VisualStatefromTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is FrameworkElement frameworkElement)
        {               
            var visualStateGroups = VisualStateManager.GetVisualStateGroups(frameworkElement);
            if (visualStateGroups != null)
            {
                var template = (DataTemplate) e.NewValue;
                var content = (FrameworkElement) template.LoadContent();
                if (VisualStateManager.GetVisualStateGroups(content) is IList list)
                {
                    var source = list.Cast<VisualStateGroup>().ToList();
                    var original = source.First();

                    source.RemoveAt(0);

                    visualStateGroups.Add(original);
                }
            }
        }
    }
}

      

Just copy and paste this step and now in your controls just add:

3 - Add attached property

<UserControl x:Class="Example.MyUserControl1"...>
  <RelativePanel x:Name="Root" local:VisualStateExtensions.VisualStatefromTemplate="{StaticResource VisualStateTemplate}" >
</UserControl>

 <UserControl x:Class="Example.MyUserControl2"...>
   <RelativePanel x:Name="Root" local:VisualStateExtensions.VisualStatefromTemplate="{StaticResource VisualStateTemplate}" >
</UserControl>

      

And with that, you can share a VisualStateGroup among multiple controls without repeating code.

+5


source







All Articles