如何用VisualStateManager代替DataTrigger实现动态绑定?

How to use VisualStateManager instead of DataTrigger to implement dynamic binding?

我尝试实现 DataTrigger,以根据视图中切换的切换按钮执行动态绑定。但是在搜索这个问题后,DataTrigger in WinRT? 似乎 Windows 通用应用程序中不可用,应该使用 VisualStateManager。

我的问题是,如何使用 VisualStateManager 实现与以下代码等效的代码?或者任何其他替代方法来设置视图模型代码后面的属性的动态绑定。

这是我在 运行 解决这个问题之前打算使用的 XAML,其中默认绑定是 OrdinaryGradePointKV 并且当切换按钮切换时绑定被更改到 HigherGradePointKV:

<ComboBox
     Grid.Row="1"
     Grid.Column="0"
     Grid.ColumnSpan="2"
     Width="60"
     HorizontalAlignment="Right"
     DisplayMemberPath="Key">
     <ComboBox.Style>
         <Style>
             <Setter Property="ComboBox.ItemsSource" Value="{Binding OrdinaryGradePointKV}"></Setter>
             <Style.Triggers>
                 <DataTrigger Binding="{Binding IsHigherToggled}" Value="True">
                     <Setter Property="ComboBox.ItemsSource"
                         Value="{Binding HigherGradePointKV}" />
                 </DataTrigger>
             </Style.Triggers>
         </Style>
     </ComboBox.Style>
 </ComboBox>

精简版的 VM 如下所示,显示了绑定的属性:

namespace LC_Points.ViewModel
{

    public class MainViewModel : ViewModelBase
    {

        /// <summary>
        /// Initializes a new instance of the MainViewModel class.
        /// </summary>
        public MainViewModel()
        {
            //call methods to initialize list data
            GetSubjectTypes();
            GetOrdinaryGradePairs();
            GetHigherGradePairs();
        }


        public List<Score> Subjects { get; set; }
        public List<StringKeyValue> HigherGradePointKV { get; set; }
        public List<StringKeyValue> OrdinaryGradePointKV { get; set; }


        //ordinary toggle button bool
        private bool _isOrdinaryToggled;
        public bool IsOrdinaryToggled
        {
            get
            {
                return _isOrdinaryToggled;
            }
            set
            {
                _isOrdinaryToggled = value;
                RaisePropertyChanged("IsOrdinaryToggled");
            }
        }

        //Higher toggle button bool property
        private bool _isHigherToggled;
        public bool IsHigherToggled
        {
            get
            {
                return _isHigherToggled;
            }
            set
            {
                _isHigherToggled = value;
                RaisePropertyChanged("IsHigherToggled");
            }
        }




        public class StringKeyValue
        {
            public string Key { get; set; }
            public int Value { get; set; }
        }


        public void GetOrdinaryGradePairs()
        {

            List<StringKeyValue> ordianryGradePointKVTemp = new List<StringKeyValue>();


            ordianryGradePointKVTemp.Add(new StringKeyValue { Key = "A1", Value = 60 });
            ordianryGradePointKVTemp.Add(new StringKeyValue { Key = "A2", Value = 50 });
            ordianryGradePointKVTemp.Add(new StringKeyValue { Key = "B1", Value = 45 });
            ordianryGradePointKVTemp.Add(new StringKeyValue { Key = "B2", Value = 40 });
            ordianryGradePointKVTemp.Add(new StringKeyValue { Key = "B3", Value = 35 });
            ordianryGradePointKVTemp.Add(new StringKeyValue { Key = "C1", Value = 30 });
            ordianryGradePointKVTemp.Add(new StringKeyValue { Key = "C2", Value = 25 });
            ordianryGradePointKVTemp.Add(new StringKeyValue { Key = "C3", Value = 20 });
            ordianryGradePointKVTemp.Add(new StringKeyValue { Key = "D1", Value = 15 });
            ordianryGradePointKVTemp.Add(new StringKeyValue { Key = "D2", Value = 10 });
            ordianryGradePointKVTemp.Add(new StringKeyValue { Key = "D3", Value = 5 });
            ordianryGradePointKVTemp.Add(new StringKeyValue { Key = "E,F,NG", Value = 0 });
            ordianryGradePointKVTemp.Add(new StringKeyValue { Key = "Pass", Value = 30 });
            ordianryGradePointKVTemp.Add(new StringKeyValue { Key = "Merit", Value = 50 });
            ordianryGradePointKVTemp.Add(new StringKeyValue { Key = "Distinction", Value = 70 });


            OrdinaryGradePointKV = ordianryGradePointKVTemp;

        }


        public void GetHigherGradePairs()
        {

            List<StringKeyValue> higherGradePointKVTemp = new List<StringKeyValue>();


            higherGradePointKVTemp.Add(new StringKeyValue { Key = "A1", Value = 100 });
            higherGradePointKVTemp.Add(new StringKeyValue { Key = "A2", Value = 90 });
            higherGradePointKVTemp.Add(new StringKeyValue { Key = "B1", Value = 85 });
            higherGradePointKVTemp.Add(new StringKeyValue { Key = "B2", Value = 80 });
            higherGradePointKVTemp.Add(new StringKeyValue { Key = "B3", Value = 75 });
            higherGradePointKVTemp.Add(new StringKeyValue { Key = "C1", Value = 70 });
            higherGradePointKVTemp.Add(new StringKeyValue { Key = "C2", Value = 65 });
            higherGradePointKVTemp.Add(new StringKeyValue { Key = "C3", Value = 60 });
            higherGradePointKVTemp.Add(new StringKeyValue { Key = "D1", Value = 55 });
            higherGradePointKVTemp.Add(new StringKeyValue { Key = "D2", Value = 50 });
            higherGradePointKVTemp.Add(new StringKeyValue { Key = "D3", Value = 45 });
            higherGradePointKVTemp.Add(new StringKeyValue { Key = "E,F,NG", Value = 0 });
            higherGradePointKVTemp.Add(new StringKeyValue { Key = "Pass", Value = 30 });
            higherGradePointKVTemp.Add(new StringKeyValue { Key = "Merit", Value = 50 });
            higherGradePointKVTemp.Add(new StringKeyValue { Key = "Distinction", Value = 70 });


            HigherGradePointKV = higherGradePointKVTemp;
        }



        public void GetSubjectTypes()
        {
            List<Score> subjectList = new List<Score>();

            // Adding Subjects to List
            subjectList.Add(new Score { Subject = "Biology" });
            subjectList.Add(new Score { Subject = "Business" });
            subjectList.Add(new Score { Subject = "Business Group" });
            subjectList.Add(new Score { Subject = "Chemistry" });
            subjectList.Add(new Score { Subject = "Classical Studies" });

            Subjects = subjectList;

        }

    }
}

如果您想坚持使用 DataTriggers,您可以使用 Microsoft.Xaml.Interactions.Core 命名空间中的 DataTriggerBehavior。添加行为的最简单方法是在 Blend 中打开项目并从资产窗格中添加它们。 Blend 会自动将 BehaviorsXamlSDKManaged 引用添加到项目中。

<ComboBox>
    <Interactivity:Interaction.Behaviors>
        <Core:DataTriggerBehavior Value="True" Binding="{Binding IsChecked, ElementName=toggleButton}">
            <Core:ChangePropertyAction PropertyName="ItemsSource" Value="{Binding OrdinaryGradePointKV}"/>
        </Core:DataTriggerBehavior>
        <Core:DataTriggerBehavior Value="False" Binding="{Binding IsChecked, ElementName=toggleButton}">
            <Core:ChangePropertyAction PropertyName="ItemsSource" Value="{Binding HighGradePointKV}"/>
        </Core:DataTriggerBehavior>
    </Interactivity:Interaction.Behaviors>
</ComboBox>

这对于您在这里的使用可能比使用视觉状态更有意义。

如果您想移动到视觉状态,则可以将视觉状态添加到普通和高级状态的页面,并让这些状态为 ComboBox 的 ItemsSource 设置动画。假设默认绑定是普通的,您的 VisualStateGroup 可能看起来像这样:

<VisualStateGroup x:Name="GradePointStates">
    <VisualState x:Name="Higher">
        <Storyboard>
            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(ItemsControl.ItemsSource)" Storyboard.TargetName="comboBox">
                <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding HigherGradePointKV}" />
            </ObjectAnimationUsingKeyFrames>
        </Storyboard>
    </VisualState>
    <VisualState x:Name="Ordinary">
    </VisualState>
</VisualStateGroup>

您可以通过代码触发 VisualState 或使用行为触发 GoToStateAction:

<ToggleButton Content="ToggleButton">
    <Interactivity:Interaction.Behaviors>
        <Core:EventTriggerBehavior EventName="Checked">
            <Core:GoToStateAction StateName="Higher"/>
        </Core:EventTriggerBehavior>
        <Core:EventTriggerBehavior EventName="Unchecked">
            <Core:GoToStateAction StateName="Ordinary"/>
        </Core:EventTriggerBehavior>
    </Interactivity:Interaction.Behaviors>
</ToggleButton>