在 WP7 + Silverlight 如何更改列表框项的视觉状态?

发布于 2024-10-30 23:07:37 字数 4872 浏览 9 评论 0 原文

我需要更改列表框项目的视觉状态。这是具有视觉状态的数据模板。我使用 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>

我绑定到此列表框的 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”的变化将列表框的视觉状态更改为“编辑”和“正常”?

谢谢

I need to change the visual state of my listbox item. Here is the DataTemplate which has the visual states. I'm using WP7 as my environment.

<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>

Heres my ListBox:

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

The ObservableCollection which I bind to this ListBox's ItemsSource is:

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");
        }
    }
}

How can I change the visual state of my ListBox to 'Edit' and 'Normal' based on the property 'CurrentState' changing?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

与君绝 2024-11-06 23:07:38

只是设法在我正在工作的 SL4 项目上实现这种情况(所以不确定它是否能在 WP7 上工作,但原始库是为 SL3 制作的,所以应该),解决方案是使用 DataStateBehaviorDataStateBehavior code> 来自 CodePlex 上的表达式混合示例 DataTemplate:

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

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

Just managed to get this happening on the SL4 project I'm working (so not sure if it's going to work on WP7, but the original library was made for SL3 so it should), the solution was to use DataStateBehavior from the Expression Blend Samples on CodePlex inside the DataTemplate:

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

If you need more than 2 states, you can also use DataStateSwitchBehavior.

表情可笑 2024-11-06 23:07:37

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

下面是执行相同操作的 WPF 行为,让您了解该行为所需的内容,但它在 Silverlight 3 / WP7 中无法工作,因为上述问题。您需要将 State 属性更改为 Binding 类型,并完成访问该绑定值的复杂过程。您可以在 TailSpin.PhoneClient.Infrastruct.ButtonCommand 中查看如何执行此操作的示例=15718049-f993-4d54-ba7b-72e0e82c16cd&displaylang=en" rel="nofollow">模式 &实践 WP7 开发指南来源 或来自 MVVM Light 的 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>

If you want to stick to a binding approach, your only real choice is a Blend Behavior. However, since Silverlight 3 (and thus WP7) doesn't support data bound behavior properties, your path is a lot more complicated. Yes, it's a PITA and yes, I hope they'll be announcing SL4 features at MIX next week.

Below is a WPF behavior that does the same thing, to give you an idea of what is required by the behavior but it won't work in Silverlight 3 / WP7 due to the above problem. You'll need to change the State property to be of type Binding and go through the convoluted process of getting access to that binding value. You can see examples of how to do this in TailSpin.PhoneClient.Infrastructure.ButtonCommand of the Patterns & Practices WP7 Dev Guide source or from MVVM 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); }
    }
}

Assuming you get it all working, you'll use the behavior like this:

<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>
紫轩蝶泪 2024-11-06 23:07:37

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

If you provide a control to act as the container for your listbox items. You can then add the logic for changing state to the code for that control using VisualStateManage.GoToState(this, "Your State", true);

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文