在UserControls中切换状态

时间:2016-07-24 12:08:16

标签: c# wpf user-controls state

我的应用程序显示UserControl以添加新对象。添加对象后,它将显示已创建对象的属性。

状态1:清空UserControl
Empty UserInput

状态2:填写用户控件
Filled UserInput

我认为我有两种方法可以实现这样的目标:

  1. 使用2种不同的可视状态创建 1 UserControl - 根据控件是否包含对象的实例来切换状态
  2. 创建 2个没有状态的UserControls ,并显示当前需要的那个。这需要一些更高级别的控制机制来添加/删除正确的控制。
  3. 在这种情况下,最佳做法是什么?做这一个或另一个有什么不利/好处?还有其他方法我还没想过吗?

2 个答案:

答案 0 :(得分:1)

我会在UserControl.Resources中创建两个数据窗口并用触发器交换它们。 CreateUserTemplate只有一个绑定到CreateUserCommand的按钮或点击事件。 EditUserTemplate是用户编辑模板。没有路径的Content="{Binding}"使用DataContext作为Content。如果我有关于您的viewmodel内容的确切详细信息,我可以为您提供有关如何在此处获取内容的更多详细信息。

我还假设viewmodel具有可为空的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中执行所有操作更容易。

答案 1 :(得分:1)

出于此特定目的,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); 
        } 
    }
    ...
}