【问题标题】:In WP7 + Silverlight how can I change the Visual State of an ListBox Item?在 WP7 + Silverlight 中,如何更改列表框项的视觉状态?
【发布时间】:2011-07-30 11:28:24
【问题描述】:

我需要更改列表框项的视觉状态。这是具有视觉状态的 DataTemplate。我使用 WP7 作为我的环境。

<DataTemplate x:Key="MessageItemTemplate">
            <Grid MinWidth="200" MinHeight="90" Width="460" Margin="0,2">
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup x:Name="Modes">
                        <VisualStateGroup.Transitions>
                            <VisualTransition GeneratedDuration="0" To="Normal">
                                <Storyboard>
                                    <DoubleAnimation Duration="0:0:0.4" To="0" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="border" d:IsOptimized="True"/>
                                </Storyboard>
                            </VisualTransition>
                            <VisualTransition GeneratedDuration="0"/>
                        </VisualStateGroup.Transitions>
                        <VisualState x:Name="Normal"/>
                        <VisualState x:Name="Edit">
                            <Storyboard>
                                <DoubleAnimation Duration="0:0:0.7" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="border" d:IsOptimized="True"/>
                            </Storyboard>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
                <VisualStateManager.CustomVisualStateManager>
                    <ic:ExtendedVisualStateManager/>
                </VisualStateManager.CustomVisualStateManager>
                <StackPanel Orientation="Vertical" d:LayoutOverrides="Width, Height" Canvas.ZIndex="10" Margin="7">
                    <TextBlock x:Name="tbTitle" Text="{Binding Path=Title, Mode=OneWay}" FontSize="24" VerticalAlignment="Top" Foreground="{StaticResource PhoneContrastBackgroundBrush}" FontWeight="Bold" Height="30" FontFamily="Microsoft New Tai Lue"/>
                    <TextBlock x:Name="tbMessage" Text="{Binding Path=Message, Mode=OneWay}" FontSize="29.333" Foreground="{StaticResource PhoneContrastBackgroundBrush}" Margin="0" FontFamily="Candara" TextWrapping="Wrap" HorizontalAlignment="Left"/>
                </StackPanel>
                <Border BorderBrush="{StaticResource PhoneAccentBrush}" BorderThickness="2" Background="{StaticResource PhoneBackgroundBrush}" CornerRadius="10" />
                <Border x:Name="border" BorderThickness="4" CornerRadius="4" BorderBrush="#FFED1212" Opacity="0" >
                    <Grid>
                        <Path Data="M149,0.16666667 L192,36.166332 L189.60141,-2.7298894 z" Fill="#FFED1212" HorizontalAlignment="Right" Margin="0,-3.031,-2.784,38.328" Stretch="Fill" UseLayoutRounding="False" Width="51.629" RenderTransformOrigin="0.5,0.5">
                            <Path.RenderTransform>
                                <CompositeTransform Rotation="2.523" TranslateX="-0.076551587038494961" TranslateY="-0.0016857129841283403"/>
                            </Path.RenderTransform>
                        </Path>
                        <Image Margin="0" Source="images/pensil.png" Stretch="Fill" Height="26" Width="26" HorizontalAlignment="Right" VerticalAlignment="Top"/>
                    </Grid>
                </Border>
            </Grid>
        </DataTemplate>

这是我的列表框:

<ListBox x:Name="SmsMessagesList" Grid.Row="1"
                 ItemsSource="{Binding Path=Model.Messages}"
                 SelectionChanged="SmsMessagesList_SelectionChanged" 
                 ItemTemplate="{StaticResource MessageItemTemplate}">
        </ListBox>

我绑定到这个 ListBox 的 ItemsSource 的 ObservableCollection 是:

public ObservableCollection<SmsMessage> Messages;

    public class SmsMessage : EntityBase
{
    private string _CurrentState;
    public string CurrentState 
    { 
        get
        {
            return _CurrentState;
        }
        set
        {
            _CurrentState = value;
            PropertyChangedHandler("CurrentState");
        }               
    }

    private string _Title;
    public string Title
    {
        get
        {
            return _Title;
        }
        set
        {
            _Title = value;
            PropertyChangedHandler("Title");
        }
    }

    private string _Message;
    public string Message
    {
        get
        {
            return _Message;
        }
        set
        {
            _Message = value;
            PropertyChangedHandler("Message");
        }
    }
}

如何根据“CurrentState”属性的变化将 ListBox 的视觉状态更改为“编辑”和“正常”?

谢谢

【问题讨论】:

    标签: silverlight windows-phone-7 datatrigger visualstatemanager


    【解决方案1】:

    如果您提供一个控件来充当列表框项的容器。然后,您可以使用 VisualStateManage.GoToState(this, "Your State", true); 将更改状态的逻辑添加到该控件的代码中

    【讨论】:

      【解决方案2】:

      如果您想坚持绑定方法,您唯一真正的选择是Blend Behavior。但是,由于 Silverlight 3(以及因此 WP7)不支持数据绑定行为属性,因此您的路径要复杂得多。是的,这是一个 PITA,是的,我希望他们将在下周的 MIX 上宣布 SL4 功能。

      下面是一个 WPF 行为,它执行相同的操作,让您了解该行为需要什么,但它在 Silverlight 3 中不起作用 / WP7 由于上述问题。您需要将State 属性更改为Binding 类型,并通过复杂的过程来访问该绑定值。您可以在TailSpin.PhoneClient.Infrastructure.ButtonCommandPatterns & Practices WP7 Dev Guide sourceMVVM Light's EventToCommand 中查看如何执行此操作的示例。

      public class StateManagementBehavior : Behavior<FrameworkElement>
      {
          public static readonly DependencyProperty StateProperty = 
              DependencyProperty.Register("State", typeof(string), 
                  typeof(StateManagementBehavior), 
                  new UIPropertyMetadata(null, PropertyChangedCallback));
      
          public static readonly DependencyProperty UseTransitionsProperty =
              DependencyProperty.Register("UseTransitions", typeof(bool), 
                  typeof(StateManagementBehavior), 
                  new UIPropertyMetadata(true));
      
          public static void PropertyChangedCallback(
              DependencyObject d, DependencyPropertyChangedEventArgs e)
          {
              var stateManagementBehavior = (StateManagementBehavior)d;
              stateManagementBehavior.GoToState();
          }
      
          protected override void OnAttached()
          {
              base.OnAttached();
      
              AssociatedObject.Loaded += (s, e) => GoToState();
          }
      
      
          private void GoToState()
          {
              if (AssociatedObject == null || State == null) return;
      
              VisualStateManager.GoToState(AssociatedObject, State, UseTransitions);
          }
      
          public string State
          {
              get { return (string)GetValue(StateProperty); }
              set { SetValue(StateProperty, value); }
          }
      
          public bool UseTransitions
          {
              get { return (bool)GetValue(UseTransitionsProperty); }
              set { SetValue(UseTransitionsProperty, value); }
          }
      }
      

      假设一切正常,您将使用如下行为:

      <DataTemplate x:Key="MessageItemTemplate">
              <Grid MinWidth="200" MinHeight="90" Width="460" Margin="0,2">
                  <i:Interactivity.Behaviors>
                      <infrastructure:StateManagementBehavior State="{Binding CurrentState}" 
                                                              UseTransitions="True" />
                  </i:Interactivity.Behaviors>
                  <VisualStateManager.VisualStateGroups>
                      ...
                  </VisualStateManager.VisualStateGroups>
      
                  ...
              </Grid>
      </DataTemplate>
      

      【讨论】:

      • 实际上问题不在于绑定,它s relatively easy to solve with a simple attached property, but VisualStateManager.GoToState annoyingly only takes a Control as the target, so it wont 无论如何都与根网格一起工作:(
      【解决方案3】:

      刚刚设法在我正在工作的 SL4 项目上实现了这一点(所以不确定它是否可以在 WP7 上工作,但原来的库是为 SL3 制作的,所以它应该),解决方案是使用 DataStateBehavior来自 DataTemplate 内的Expression Blend Samples on CodePlex

      <i:Interaction.Behaviors>
          <ei:DataStateBehavior Binding="{Binding IsEditMode}" Value="True" TrueState="Edit" FalseState="Normal"/>
      </i:Interaction.Behaviors>
      

      如果需要2个以上的状态,也可以使用DataStateSwitchBehavior

      【讨论】:

        猜你喜欢
        • 2017-01-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多