在 UserControls 中切换状态
Switching between states in UserControls
我的应用程序显示了一个用于添加新对象的 UserControl。添加对象后,它会显示已创建对象的属性。
状态 1:空用户控件
状态 2:填充用户控件
我想有两种方法可以实现这样的事情:
- 创建具有 2 种不同视觉状态的 1 UserControl - 根据控件是否包含对象实例在状态之间切换
- 创建 2 个没有状态的用户控件 并显示当前需要的那个。这需要一些更高级别的控制机制来 add/remove 正确的控制。
在这种情况下,最佳做法是什么?什么是 dis/advantages 来做这两者?还有没有其他我没有想到的方法?
我会在 UserControl.Resources
中创建两个数据模板并用触发器交换它们。 CreateUserTemplate
只是有一个绑定到 CreateUserCommand
或点击事件的按钮。 EditUserTemplate
为用户编辑模板。 Content="{Binding}"
没有路径使用 DataContext
作为 Content
。如果我有您的视图模型内容的确切详细信息,我可以为您提供有关如何在此处获取内容的更多细节。
我还假设视图模型有一个可为 null 的 UserID
属性。
<ContentControl
Content="{Binding}"
>
<ContentControl.Style>
<Style TargetType="ContentControl">
<!-- Default has to go in a setter in the Style, not an
attribute on the ContentControl tag -->
<Setter
Property="ContentTemplate"
Value="{StaticResource EditUserTemplate}"
/>
<Style.Triggers>
<DataTrigger Binding="{Binding UserID}" Value="{x:Null}">
<Setter
Property="ContentTemplate"
Value="{StaticResource CreateUserTemplate}"
/>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
您可以改为编写 DataTemplateSelector,但对于这种微不足道的事情,我发现在 XAML 中做所有事情都更容易。
为此特定目的,WPF 提供了VisualStateManager。
<UserControl ...>
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="States">
<VisualState x:Name="WithoutObject">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="WithoutObjectPanel" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="WithObjectPanel" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="WithObject">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="WithoutObjectPanel" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="WithObjectPanel" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<StackPanel x:Name="WithoutObjectPanel" Visibility="Hidden">
<TextBlock Text="Without object :("/>
</StackPanel>
<StackPanel x:Name="WithObjectPanel" Visibility="Visible">
<TextBlock Text="With object :) !!!!"/>
</StackPanel>
</Grid>
</UserControl>
UserControl.cs
public partial class UserControl1 : UserControl
{
object _anObject;
public object AnObject
{
get { return _anObject; }
set { _anObject = value;
if(value == null) VisualStateManager.GoToState(this, "WithoutObject", true);
else VisualStateManager.GoToState(this, "WithObject", true);
}
}
...
}
我的应用程序显示了一个用于添加新对象的 UserControl。添加对象后,它会显示已创建对象的属性。
状态 1:空用户控件
状态 2:填充用户控件
我想有两种方法可以实现这样的事情:
- 创建具有 2 种不同视觉状态的 1 UserControl - 根据控件是否包含对象实例在状态之间切换
- 创建 2 个没有状态的用户控件 并显示当前需要的那个。这需要一些更高级别的控制机制来 add/remove 正确的控制。
在这种情况下,最佳做法是什么?什么是 dis/advantages 来做这两者?还有没有其他我没有想到的方法?
我会在 UserControl.Resources
中创建两个数据模板并用触发器交换它们。 CreateUserTemplate
只是有一个绑定到 CreateUserCommand
或点击事件的按钮。 EditUserTemplate
为用户编辑模板。 Content="{Binding}"
没有路径使用 DataContext
作为 Content
。如果我有您的视图模型内容的确切详细信息,我可以为您提供有关如何在此处获取内容的更多细节。
我还假设视图模型有一个可为 null 的 UserID
属性。
<ContentControl
Content="{Binding}"
>
<ContentControl.Style>
<Style TargetType="ContentControl">
<!-- Default has to go in a setter in the Style, not an
attribute on the ContentControl tag -->
<Setter
Property="ContentTemplate"
Value="{StaticResource EditUserTemplate}"
/>
<Style.Triggers>
<DataTrigger Binding="{Binding UserID}" Value="{x:Null}">
<Setter
Property="ContentTemplate"
Value="{StaticResource CreateUserTemplate}"
/>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
您可以改为编写 DataTemplateSelector,但对于这种微不足道的事情,我发现在 XAML 中做所有事情都更容易。
为此特定目的,WPF 提供了VisualStateManager。
<UserControl ...>
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="States">
<VisualState x:Name="WithoutObject">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="WithoutObjectPanel" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="WithObjectPanel" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="WithObject">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="WithoutObjectPanel" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="WithObjectPanel" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<StackPanel x:Name="WithoutObjectPanel" Visibility="Hidden">
<TextBlock Text="Without object :("/>
</StackPanel>
<StackPanel x:Name="WithObjectPanel" Visibility="Visible">
<TextBlock Text="With object :) !!!!"/>
</StackPanel>
</Grid>
</UserControl>
UserControl.cs
public partial class UserControl1 : UserControl
{
object _anObject;
public object AnObject
{
get { return _anObject; }
set { _anObject = value;
if(value == null) VisualStateManager.GoToState(this, "WithoutObject", true);
else VisualStateManager.GoToState(this, "WithObject", true);
}
}
...
}