【问题标题】:How do I reuse VisualState, VisualStateGroup and VsualStateManager in shared resource?如何在共享资源中重用 VisualState、VisualStateGroup 和 VsualStateManager?
【发布时间】:2015-08-10 06:06:29
【问题描述】:

我创建了许多按钮,它们在我的 Windows Phone 项目中使用相同的 VisualStateManager、VisualStateGroup 和 VisualState。然后,我想将它们全部重用为共享资源,作为其他类型的元素,例如边距、颜色等。

但我发现只有重用情节提要的方法,如果我可以重用所有 VisualState 会更好。

可重用的VisualState有解决方案吗?

【问题讨论】:

    标签: wpf xaml windows-phone windows-store-apps


    【解决方案1】:

    我发现我在 Windows 10 UWP 应用程序上测试的解决方案,我测试了几个选项,例如反序列化 XAML、克隆等,但最后我发现以下是最好的解决方案:

    1 - 将 VisualStateGroup 设置为资源

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

    这是第一个技巧,通过它您可以多次“加载”VisualStateGroup

    2 - 实现附加属性以设置为 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);
                    }
                }
            }
        }
    }
    

    这一步只是复制粘贴,现在在你的控件中简单的添加:

    3 - 添加附加属性

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

    这样您就可以在多个控件之间共享一个 VisualStateGroup 而无需重复代码。

    【讨论】:

    • 好主意!! ??
    • 它似乎不起作用,但我不确定我是否做得正确。我已将local:VisualStateExtensions... 应用于第一个ScrollViewer,但也尝试了子Grid 来更改某种文本框样式。文本框样式在ResourceDirectory 中也是通用的。这可以用来直接更改其他样式资源吗?在针对其他样式(在同一 ResourceDirectory 内)时,它不会给出任何构建/运行时错误,但它不会在需要时更改字体大小。
    • 添加了一个与我的问题相关的问题:stackoverflow.com/questions/59750059/…
    猜你喜欢
    • 2014-11-28
    • 1970-01-01
    • 1970-01-01
    • 2021-05-04
    • 1970-01-01
    • 2014-02-11
    • 2016-11-26
    • 2011-07-05
    • 2021-10-10
    相关资源
    最近更新 更多