更改视图状态的最佳做法是什么?

时间:2023-01-20 22:54:03

I have a component with two Pie Charts that display percentages at two specific dates (think start and end values). But, I have three views: Start Value only, End Value only, or show Both. I am using a ToggleButtonBar to control the display. What is the best practice for changing this kind of view state? Right now (since this code was inherited), the view states are changed in an ActionScript function which sets the visible and includeInLayout properties on each Pie Chart based on the selectedIndex of the ToggleButtonBar, but, this just doesn't seem like the best way to do this - not very dynamic. I'd like to be able to change the state based on the name of the selectedItem, in case the order of the ToggleButtons changes, and since I am storing the name of the selectedItem for future reference.

我有一个带有两个饼图的组件,它在两个特定日期显示百分比(想想开始值和结束值)。但是,我有三个视图:仅限起始值,仅限结束值,或显示两者。我正在使用ToggleButtonBar来控制显示。改变这种视图状态的最佳实践是什么?现在(因为此代码是继承的),视图状态在ActionScript函数中更改,该函数根据ToggleButtonBar的selectedIndex在每个饼图上设置visible和includeInLayout属性,但是,这似乎不是最好的方法做到这一点 - 不是很有活力。我希望能够根据selectedItem的名称更改状态,以防ToggleButtons的顺序发生变化,并且因为我存储了selectedItem的名称以供将来参考。

Would using States be better? If so, what would be the best way to implement this?

使用国家会更好吗?如果是这样,那么实现这个的最佳方法是什么?

Thanks.

Current logic:

private function pieTypeToggleButtonBar_itemClickHandler():void
{
    // Show/Hide the appropriate Pie Charts based on the user's selection
    switch (pieTypeToggleButtonBar.selectedIndex)
    {
        // "Start Value" is selected
        case 0:
        {
            // Hide the End Value Pie Chart
            endValuePieChartVBox.visible = false;
            endValuePieChartVBox.includeInLayout = false;

            // Show the Start Value Pie Chart
            startValuePieChartVBox.includeInLayout = true;
            startValuePieChartVBox.visible = true;

            break;
        }
        // "End Value" is selected
        case 1:
        {
            // Hide the Start Value Pie Chart
            startValuePieChartVBox.visible = false;
            startValuePieChartVBox.includeInLayout = false;

            // Show the End Value Pie Chart
            endValuePieChartVBox.includeInLayout = true;
            endValuePieChartVBox.visible = true;

            break;
        }
        // "Both" is selected
        case 2:
        {
            // Show the Start Value Pie Chart
            startValuePieChartVBox.includeInLayout = true;
            startValuePieChartVBox.visible = true;

            // Show the End Value Pie Chart
            endValuePieChartVBox.includeInLayout = true;
            endValuePieChartVBox.visible = true;

            break;
        } 
    }
}

<mx:ToggleButtonBar id="pieTypeToggleButtonBar" selectedIndex="1" 
    itemClick="pieTypeToggleButtonBar_itemClickHandler()">
    <mx:Array>
        <mx:Object name="startValue" label="Start Value" />

        <mx:Object name="endValue" label="End Value" />

        <mx:Object name="both" label="Both" />
    </mx:Array>
</mx:ToggleButtonBar>

3 个解决方案

#1


Since the currentState property takes a String, which maps to the name property of a state, then it sounds like using <mx:states> would work well in your case. In fact I use states often for toggling between views in just the way you describe -- setting visible and includeInLayout properties of components (usually Canvas components, or other sorts of containers) with SetProperty:

由于currentState属性采用String(映射到状态的name属性),因此听起来像使用 在您的情况下会很好用。实际上,我通常使用状态来按照您描述的方式在视图之间切换 - 使用SetProperty设置组件的可见和includeInLayout属性(通常是Canvas组件或其他类型的容器):

<mx:states>
    <mx:State name="View State 1">
        <mx:SetProperty target="{component1}" name="visible" value="true" />
        <mx:SetProperty target="{component2}" name="visible" value="false" />
        <mx:SetProperty target="{component3}" name="visible" value="false" />
        <mx:SetProperty target="{component1}" name="includeInLayout" value="true" />
        <mx:SetProperty target="{component2}" name="includeInLayout" value="false" />
        <mx:SetProperty target="{component3}" name="includeInLayout" value="false" />
    </mx:State>
    <mx:State name="View State 2">
        <mx:SetProperty target="{component1}" name="visible" value="false" />
        <mx:SetProperty target="{component2}" name="visible" value="true" />
        <mx:SetProperty target="{component3}" name="visible" value="false" />
        <mx:SetProperty target="{component1}" name="includeInLayout" value="false" />
        <mx:SetProperty target="{component2}" name="includeInLayout" value="true" />
        <mx:SetProperty target="{component3}" name="includeInLayout" value="false" />
    </mx:State>
    <mx:State name="View State 3">
        <mx:SetProperty target="{component1}" name="visible" value="false" />
        <mx:SetProperty target="{component2}" name="visible" value="false" />
        <mx:SetProperty target="{component3}" name="visible" value="true" />
        <mx:SetProperty target="{component1}" name="includeInLayout" value="false" />
        <mx:SetProperty target="{component2}" name="includeInLayout" value="false" />
        <mx:SetProperty target="{component3}" name="includeInLayout" value="true" />
    </mx:State>
</mx:states>

<mx:Script>
    <![CDATA[

        import mx.binding.utils.BindingUtils;
        import mx.binding.utils.ChangeWatcher;

        private function this_creationComplete(event:Event):void
        {
                // Use BindingUtils.bindSetter to hook into selectedIndex-change events
            var cw:ChangeWatcher = BindingUtils.bindSetter(setState, myBar, "selectedIndex");
        }

        private function setState(index:int):void
        {
            currentState = myBar.getChildren()[index].label;
        }

    ]]>
</mx:Script>

<mx:ToggleButtonBar id="myBar">
    <mx:dataProvider>
        <mx:Array>
            <mx:String>View State 1</mx:String>
            <mx:String>View State 2</mx:String>
            <mx:String>View State 3</mx:String>
        </mx:Array>
    </mx:dataProvider>
</mx:ToggleButtonBar>

<mx:Canvas id="component1">
    <mx:Text text="Component 1" />
</mx:Canvas>

<mx:Canvas id="component2">
    <mx:Text text="Component 2" />
</mx:Canvas>

<mx:Canvas id="component3">
    <mx:Text text="Component 3" />
</mx:Canvas>

... following this general pattern. Hope it helps!

......遵循这种一般模式。希望能帮助到你!

#2


The simplest way to do this would be to use the ViewStack component. That way you just select the selectedIndex and all the other panels will hide (watch out for initialization problems with ViewStacks).

最简单的方法是使用ViewStack组件。这样您只需选择selectedIndex,所有其他面板将隐藏(注意ViewStacks的初始化问题)。

Because of the problems i have had with ViewStacks in the past i would probably be inclined to use view states though as an alternative. States have their own problems but they are definitely feasible for this particular problem.

由于我过去在ViewStacks中遇到的问题,我可能倾向于使用视图状态作为替代方案。各国都有自己的问题,但对于这一特定问题它们肯定是可行的。

If i were you i would look into either of these options as a solution as the functionality created about has already been created with a standard api.... try and stick to using mx components if they fit your specific needs rather than reinventing the wheel all the time

如果我是你,我将把这些选项中的任何一个作为解决方案,因为已经使用标准api创建了所创建的功能....尝试并坚持使用mx组件,如果它们符合您的特定需求而不是重新发明*每时每刻

#3


The use of states in the first component completely misses the point. You shouldn't be setting visible and includeInLayout, you should be ADDING and REMOVING the components using AddChild and RemoveChild. The use of visible and includeInLayout to control object's state on the screen is a bastardization of their intent. Unfortunately, since Flex doesn't have any sort of conditional logic tags or even conditional attributes to add/remove elements, people often fall back on those two tags. Sometimes that's the only practical thing to do, but in your case or in any case where you have a 'switch' statement, you definitely want to use states.

在第一个组件中使用状态完全忽略了这一点。您不应该设置visible和includeInLayout,您应该使用AddChild和RemoveChild添加和删除组件。使用visible和includeInLayout来控制屏幕上对​​象的状态是他们意图的混蛋。不幸的是,由于Flex没有任何类型的条件逻辑标签甚至条件属性来添加/删除元素,人们常常会依赖这两个标签。有时这是唯一可行的事情,但在你的情况下,或者在你有'switch'语句的任何情况下,你肯定想要使用状态。

#1


Since the currentState property takes a String, which maps to the name property of a state, then it sounds like using <mx:states> would work well in your case. In fact I use states often for toggling between views in just the way you describe -- setting visible and includeInLayout properties of components (usually Canvas components, or other sorts of containers) with SetProperty:

由于currentState属性采用String(映射到状态的name属性),因此听起来像使用 在您的情况下会很好用。实际上,我通常使用状态来按照您描述的方式在视图之间切换 - 使用SetProperty设置组件的可见和includeInLayout属性(通常是Canvas组件或其他类型的容器):

<mx:states>
    <mx:State name="View State 1">
        <mx:SetProperty target="{component1}" name="visible" value="true" />
        <mx:SetProperty target="{component2}" name="visible" value="false" />
        <mx:SetProperty target="{component3}" name="visible" value="false" />
        <mx:SetProperty target="{component1}" name="includeInLayout" value="true" />
        <mx:SetProperty target="{component2}" name="includeInLayout" value="false" />
        <mx:SetProperty target="{component3}" name="includeInLayout" value="false" />
    </mx:State>
    <mx:State name="View State 2">
        <mx:SetProperty target="{component1}" name="visible" value="false" />
        <mx:SetProperty target="{component2}" name="visible" value="true" />
        <mx:SetProperty target="{component3}" name="visible" value="false" />
        <mx:SetProperty target="{component1}" name="includeInLayout" value="false" />
        <mx:SetProperty target="{component2}" name="includeInLayout" value="true" />
        <mx:SetProperty target="{component3}" name="includeInLayout" value="false" />
    </mx:State>
    <mx:State name="View State 3">
        <mx:SetProperty target="{component1}" name="visible" value="false" />
        <mx:SetProperty target="{component2}" name="visible" value="false" />
        <mx:SetProperty target="{component3}" name="visible" value="true" />
        <mx:SetProperty target="{component1}" name="includeInLayout" value="false" />
        <mx:SetProperty target="{component2}" name="includeInLayout" value="false" />
        <mx:SetProperty target="{component3}" name="includeInLayout" value="true" />
    </mx:State>
</mx:states>

<mx:Script>
    <![CDATA[

        import mx.binding.utils.BindingUtils;
        import mx.binding.utils.ChangeWatcher;

        private function this_creationComplete(event:Event):void
        {
                // Use BindingUtils.bindSetter to hook into selectedIndex-change events
            var cw:ChangeWatcher = BindingUtils.bindSetter(setState, myBar, "selectedIndex");
        }

        private function setState(index:int):void
        {
            currentState = myBar.getChildren()[index].label;
        }

    ]]>
</mx:Script>

<mx:ToggleButtonBar id="myBar">
    <mx:dataProvider>
        <mx:Array>
            <mx:String>View State 1</mx:String>
            <mx:String>View State 2</mx:String>
            <mx:String>View State 3</mx:String>
        </mx:Array>
    </mx:dataProvider>
</mx:ToggleButtonBar>

<mx:Canvas id="component1">
    <mx:Text text="Component 1" />
</mx:Canvas>

<mx:Canvas id="component2">
    <mx:Text text="Component 2" />
</mx:Canvas>

<mx:Canvas id="component3">
    <mx:Text text="Component 3" />
</mx:Canvas>

... following this general pattern. Hope it helps!

......遵循这种一般模式。希望能帮助到你!

#2


The simplest way to do this would be to use the ViewStack component. That way you just select the selectedIndex and all the other panels will hide (watch out for initialization problems with ViewStacks).

最简单的方法是使用ViewStack组件。这样您只需选择selectedIndex,所有其他面板将隐藏(注意ViewStacks的初始化问题)。

Because of the problems i have had with ViewStacks in the past i would probably be inclined to use view states though as an alternative. States have their own problems but they are definitely feasible for this particular problem.

由于我过去在ViewStacks中遇到的问题,我可能倾向于使用视图状态作为替代方案。各国都有自己的问题,但对于这一特定问题它们肯定是可行的。

If i were you i would look into either of these options as a solution as the functionality created about has already been created with a standard api.... try and stick to using mx components if they fit your specific needs rather than reinventing the wheel all the time

如果我是你,我将把这些选项中的任何一个作为解决方案,因为已经使用标准api创建了所创建的功能....尝试并坚持使用mx组件,如果它们符合您的特定需求而不是重新发明*每时每刻

#3


The use of states in the first component completely misses the point. You shouldn't be setting visible and includeInLayout, you should be ADDING and REMOVING the components using AddChild and RemoveChild. The use of visible and includeInLayout to control object's state on the screen is a bastardization of their intent. Unfortunately, since Flex doesn't have any sort of conditional logic tags or even conditional attributes to add/remove elements, people often fall back on those two tags. Sometimes that's the only practical thing to do, but in your case or in any case where you have a 'switch' statement, you definitely want to use states.

在第一个组件中使用状态完全忽略了这一点。您不应该设置visible和includeInLayout,您应该使用AddChild和RemoveChild添加和删除组件。使用visible和includeInLayout来控制屏幕上对​​象的状态是他们意图的混蛋。不幸的是,由于Flex没有任何类型的条件逻辑标签甚至条件属性来添加/删除元素,人们常常会依赖这两个标签。有时这是唯一可行的事情,但在你的情况下,或者在你有'switch'语句的任何情况下,你肯定想要使用状态。