如何将控件的VisualStateManager状态绑定到viewmodel中的属性?可以吗?
我知道我们可以使用
VisualStateManager.GoToState(this,"SomeState1",true);
Run Code Online (Sandbox Code Playgroud)
进入SomeState1,但现在如何回到基本状态,就像没有状态一样,加载控件的状态.
VisualStateManager.GoToState(this,"base",true);
// OR
VisualStateManager.GoToState(this,"",true);
// OR
VisualStateManager.GoToState(this,null,true);
Run Code Online (Sandbox Code Playgroud)
问题是如果没有这种方式返回到初始状态或基本状态,那么我将不得不始终创建第一个状态,并在构造函数中转到控制开始时的第一个状态.
我没有找到任何文档,所以我尝试所有组合,但没有找到任何工作..
有一些非常有用的工具可以在运行时调试WPF应用程序,如Snoop,WPF Inspector和Xaml Spy,它们允许您偷偷看看正在运行的应用程序和监视属性值,DataContext更改,路由事件甚至触发器切换.
但我在其中任何一个中找不到的是如何在运行时监视特定选定控件上的状态之间的VisualStateManager(VSM)转换.
是否有任何工具可以帮助找出控件未进入特定预期状态的原因(考虑到此应用程序/库的源代码缺失)?
更新:当您无法访问源时,问题主要在于调试已编译的代码.对于有权访问源代码的情况,可以很好地解释其中一种方法.
我需要更改控件的状态然后执行一些操作.具体来说,我想在隐藏控件之前运行动画.我想做那样的事情:
VisualStateManager.GoToState(control, "Hidden", true); // wait until the transition animation is finished
ParentControl.Children.Remove(control);
Run Code Online (Sandbox Code Playgroud)
问题是过渡动画是异步运行的,因此在动画启动后立即从可视树中删除控件.
那我该如何等待动画完成呢?
使用Silverlight 4和WPF 4,我正在尝试创建一个按钮样式,当按钮被鼠标悬停时,它会改变任何包含文本的文本颜色.因为我试图使它与Silverlight和WPF兼容,所以我使用了可视状态管理器:
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="outerBorder" CornerRadius="4" BorderThickness="1" BorderBrush="#FF757679">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="0" To="#FFFEFEFE"
Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)"
Storyboard.TargetName="contentPresenter"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<Border x:Name="Background" CornerRadius="3" BorderThickness="1" BorderBrush="Transparent">
<Grid>
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}"/>
</Grid>
</Border>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
Run Code Online (Sandbox Code Playgroud)
由于这是一个常规旧按钮的模板,我知道不能保证里面甚至有一个文本块,起初我不确定这是否可能.奇怪的是,如果按钮声明如下,文本颜色确实会改变:
<Button Content="Hello, World!" />
Run Code Online (Sandbox Code Playgroud)
但如果按钮声明如下,它不会改变:
<Button>
<TextBlock Text="Hello, World!" /> <!-- Same result with <TextBlock>Hello, World </TextBlock> -->
</Button>
Run Code Online (Sandbox Code Playgroud)
即使可视树(在snoop中检查时)是相同的(Button - > ContentPresenter …
就在我认为我理解的时候VisualStateManager,有些东西证明我错了.
我正在使用WPF 4,我试图简单地将鼠标放大,然后在鼠标离开时将其缩小.我想我只是在a中定义每个状态VisualStateGroup然后VisualTransition用a 指定a GeneratedDuration:
<Border x:Name="PART_Root" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" RenderTransformOrigin="0.5,0.5">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:1"/>
</VisualStateGroup.Transitions>
<VisualState Name="Normal"/>
<VisualState Name="MouseOver">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="scaleTransform" Storyboard.TargetProperty="ScaleX" To="1.5" Duration="0"/>
<DoubleAnimation Storyboard.TargetName="scaleTransform" Storyboard.TargetProperty="ScaleY" To="1.5" Duration="0"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border.RenderTransform>
<ScaleTransform x:Name="scaleTransform" ScaleX="1" ScaleY="1"/>
</Border.RenderTransform>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
Run Code Online (Sandbox Code Playgroud)
由于我有一个全能VisualTransition的GeneratedDuration,我期待VSM生成中间动画.也就是说,鼠标悬停在控件上应该在ScaleTransform1秒内将属性设置为1到1.5.与mousing相同.相反,延迟1秒,然后ScaleTransform属性立即捕捉到1.5或回到1.
如果我手动指定转换如下,那么我得到所需的行为:
<VisualStateGroup.Transitions>
<VisualTransition From="Normal" To="MouseOver">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="scaleTransform" Storyboard.TargetProperty="ScaleX" To="1.5" …Run Code Online (Sandbox Code Playgroud) 我正在使用Windows 8样式(以前称为metro)创建WPF按钮.
我希望按钮的聚焦状态以稳固的背景显示.当鼠标悬停在控件上时,我希望背景稍微变暗以创建可以单击按钮的视觉提示.
不幸的是,我在下面写的XAML不起作用.聚焦状态显示正确,但当鼠标在控件上时,背景不会像我希望的那样变暗.
<Color x:Key="DoxCycleGreen">
#FF8DC63F
</Color>
<!-- Soft Interface : DoxCycle Green -->
<Color x:Key="DoxCycleGreenSoft">
#FFC0DC8F
</Color>
<Style x:Key="MetroButton" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="RootElement">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal" />
<VisualState Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundColor" Storyboard.TargetProperty="Color" To="{StaticResource DoxCycleGreen}" Duration="0:0:0.150" />
<ColorAnimation Storyboard.TargetName="FontColor" Storyboard.TargetProperty="Color" To="White" Duration="0:0:0.150" />
</Storyboard>
</VisualState>
<VisualState Name="Focused">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundColor" Storyboard.TargetProperty="Color" To="{StaticResource DoxCycleGreenSoft}" Duration="0:0:0.150" />
<ColorAnimation Storyboard.TargetName="FontColor" Storyboard.TargetProperty="Color" To="White" Duration="0:0:0.150" />
</Storyboard>
</VisualState>
<VisualState Name="Pressed">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundColor" …Run Code Online (Sandbox Code Playgroud) 我在Expression Blend中定义了以下两种状态.我一直在努力遵循这个指南,但是当我需要有关如何以及何时改变状态的信息时,我觉得这让我感到不知所措.

根据指南,我要附加一个行为(我假设"GotoState")给我UserControl- 不幸的是我不认为我实际上有User Control- 而且即使我这样做,我是否必须对我PortraitState和我的行为都附加行为LandscapeState?
看来我可以附加一个GotoState我的LayoutRoot元素.那么我是否将这种行为与两种状态中的行为联系起来?任何帮助将不胜感激.
*编辑:我正在我的xaml.cs文件中玩,并认为这可能是以编程方式执行此操作的方法.调试和更改方向时,我进入开关盒并找到正确的方向.然而,国家从未切换过.我究竟做错了什么?
protected override void OnOrientationChanged(OrientationChangedEventArgs e)
{
switch (e.Orientation)
{
case PageOrientation.Landscape:
ExtendedVisualStateManager.GoToElementState(root:this.LayoutRoot, stateName: "LandscapeState", useTransitions: true);
break;
case PageOrientation.LandscapeRight:
ExtendedVisualStateManager.GoToElementState(root:this.LayoutRoot, stateName: "LandscapeState", useTransitions: true);
break;
case PageOrientation.LandscapeLeft:
ExtendedVisualStateManager.GoToElementState(root:LayoutRoot, stateName: "LandscapeState", useTransitions: true);
break;
case PageOrientation.Portrait:
ExtendedVisualStateManager.GoToElementState(root:this.LayoutRoot, stateName: "PortraitState", useTransitions: true);
break;
case PageOrientation.PortraitUp:
ExtendedVisualStateManager.GoToElementState(root:this.LayoutRoot, stateName: "PortraitState", useTransitions: true);
break;
case PageOrientation.PortraitDown:
ExtendedVisualStateManager.GoToElementState(root:this.LayoutRoot, stateName: "PortraitState", useTransitions: true);
break;
default: …Run Code Online (Sandbox Code Playgroud) 我在DataTemplate中有一些控件,我想控制它的按下状态行为.我做了以下我只是在DataTemplate中放入VisualStateManager但它似乎不起作用.我想我可以理解下面要做的事情.是否可以在DataTemplate标签内部进行内联?
<ItemsControl ItemsSource="{Binding Items}">
....
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid ...>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
...
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderThickness" Storyboard.TargetName="GridItemBorder">
<DiscreteObjectKeyFrame KeyTime="0" Value="3"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Border" ...>
...
</Border>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Run Code Online (Sandbox Code Playgroud) silverlight xaml datatemplate visualstatemanager windows-phone-7
我有一个用户界面,适应不同的设备形状因素使用AdaptiveTrigger.特别是,SplitView当最小窗口宽度分别为1000 epx和600 epx时,我有一个带有两个状态触发器的基于shell的菜单.600 epx状态触发器可以在横向模式下触发某些移动设备,具体取决于它们的形状因子和比例因子,这是预期的行为.
但是,我注意到在桌面上,一旦我改变主题设置,例如在暗和亮模式之间切换,改变强调颜色或切换高,600 epx状态触发器在后台触发(ShellSplitView.DisplayMode从更改Overlay到CompactOverlay)对比模式; 在移动模拟器和设备上,当我转到"设置"应用,更改主题设置并返回到我的应用时,它会触发.最奇怪的是,这只发生在默认状态,并且只有在我通过调整桌面上的窗口大小或通过旋转移动仿真器或设备来触发任何状态触发器之后.返回应用程序后再次调整大小/旋转会使问题消失.我以前没有见过这种在任何其他应用程序,包括微软的应用程序或任何第三方应用程序UWP.
我已经确认这不是由于某些其他代码干扰状态触发器造成的,通过在一个空白的UWP项目中成功地再现问题,其中单个页面只包含SplitView任意数量的可视状态(以及一些文本内容):
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="1000"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="ShellSplitView.DisplayMode" Value="Inline"/>
<Setter Target="ShellSplitView.IsPaneOpen" Value="True"/>
</VisualState.Setters>
</VisualState>
<VisualState>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="600"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="ShellSplitView.DisplayMode" Value="CompactOverlay"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<SplitView
x:Name="ShellSplitView"
CompactPaneLength="48"
DisplayMode="Overlay"
IsPaneOpen="False"
OpenPaneLength="256">
<SplitView.Content>
<TextBlock Text="Content"/>
</SplitView.Content>
<SplitView.Pane>
<TextBlock Text="Pane"/>
</SplitView.Pane>
</SplitView>
</Grid>
</Page>
Run Code Online (Sandbox Code Playgroud)
您可以尝试通过创建空白UWP项目,用上述XAML替换MainPage.xaml的内容并运行项目来自己重现问题.
考虑到我所做的只是更改主题设置,我不明白为什么任何状态触发器会触发.实际上,根据MSDN 上的 …
wpf ×5
silverlight ×4
xaml ×4
c# ×2
animation ×1
button ×1
datatemplate ×1
debugging ×1
mvvm ×1
runtime ×1
styling ×1
transitions ×1
uwp ×1
vsm ×1
windows-10 ×1
winrt-xaml ×1