对通过ContentPresenter显示的UserControl动画DependencyProperty

时间:2013-10-04 15:33:24

标签: wpf animation user-controls visualstatemanager contentpresenter

在WPF中,我有一个ListBox,其列表由UserControls组成。控件旨在导航到应用程序中的不同屏幕。每个UserControl(称为NavigationButton)都有一个图标和文本。图标主要是多个Path对象的组合,因此每个图标都是自己的UserControl,并且使用ContentPresenter显示它们。我希望能够根据屏幕的不同状态为图标的颜色设置动画,但尝试了很多选项并且无法执行此操作。

以下是NavigationButton的精简版:

<DockPanel Margin="12,0,12,0">

        <!-- Icon -->
        <ContentPresenter x:Name="Content_Icon" Content="{Binding}" Width="20"/>

        <!-- Text -->
        <Grid Margin="9,0,0,0">
            <TextBlock x:Name="TextBlock_Text" Text="{Binding ScreenName, Converter={StaticResource StringToStringUpperConverter}}" VerticalAlignment="Center" 
                       FontSize="15" Foreground="#FFF2F2F2" />
        </Grid>

基本上,我需要为ContentPresenter上的属性设置动画,但不知道如何访问它。

这是托管NavigationButtons的ListBox:

        <ListBox DockPanel.Dock="Top" ItemsSource="{Binding ScreenViewModels}" 
             SelectedItem="{Binding SelectedScreenViewModel}">

        <ListBox.ItemTemplate>
            <DataTemplate>
                <my:NavigationButton/>
            </DataTemplate>
        </ListBox.ItemTemplate>

我创建了一个基本UserControl(称为IconBaseControl),所有这些图标UserConrols都可以继承。基本控件有一个Brush DependencyProperty,名为IconFill。图标上可以更改的路径部分绑定到此属性:

<Path Data="<data>" Fill="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type my:IconBaseControl}}, Path=IconFill}"

我知道绑定工作正常,因为当我更改UserControl上的默认颜色时颜色会发生变化。理想情况下,我想使用VisualStateManager,因为会有许多不同的状态。所以,我在NavigationButton上有一个VisualStateManager,UserControl包含托管图标的ContentPresenter(所有继承IconBaseControl的UserControl),名为Content_Icon。我在其中一个州尝试了类似的东西:

<VisualState x:Name="Deselected">
            <Storyboard>

                <ColorAnimation Storyboard.TargetName="TextBlock_Text" Storyboard.TargetProperty="Foreground.Color"
                        To="#FF5e5e5e" Duration="0"/>

                <ColorAnimation Storyboard.TargetName="Content_Icon" Storyboard.TargetProperty="IconFill"
                        To="#FF5e5e5e" Duration="0"/>

            </Storyboard>
</VisualState>

但是我收到以下错误:

InvalidOperationException:无法解析属性路径“IconFill”中的所有属性引用。验证适用的对象是否支持属性。

我也试过用这样的东西绑定故事板的属性:

Storyboard.TargetProperty="(IconBaseControl.IconFill)

但是得到这个错误:

Windows Presentation Foundation(WPF)项目不支持IconBaseControl。

我也尝试过乱码,但无法弄清楚如何将ContentPresenter转换为IconBaseControl。我认为ContentTemplate属性是可行的,但它没什么。

有关如何动画此属性的任何建议?几乎可以开放:)我在VB.Net中编码,但任何C#建议都很好。

提前致谢。

编辑:包含NavigationButton的代码

1 个答案:

答案 0 :(得分:1)

我发现创建WPF控件的子类可能会变得混乱,除非是一个非常高级的问题,否则没有必要。在我看来,创建IconBaseControl作为UserControl的孩子在你的场景中是过度的。

这是我的建议,假设您正在使用MVVM:将IconBaseControl创建为普通的UserControl。只需在文件后面创建一个带有IconControl.xaml.cs代码的IconControl.xaml,就像使用任何其他视图一样。

以下是IconControl中的内容示例:

<UserControl>
    <Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Grid.Style>
        <Style>
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsSelected}" Value="True">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)" To="#FF5e5e5e" Duration="0:0:0" />
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                    <DataTrigger.ExitActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)" To="White" Duration="0:0:0" />
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.ExitActions>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Grid.Style>

    <Image Source="Icon.jpeg" />

    <TextBlock Text="{Binding PageName}" Grid.Column="1" />

</Grid>
</UserControl>`

请注意,周围网格的背景将根据对DataContext上名为IsSelected的值的绑定而更改。所以此时你需要创建一个名为IconControlViewModel.cs的ViewModel,它将IsSelected boolean公开为依赖属性。

最后是包含这些导航按钮的视图:

<UserControl>

    <ItemsControl ItemsSource="{Binding ListOf_IconControlViewModels}">
        <ItemsControl.ItemTemplate>
            <DataTemplate DataType="{x:Type IconControlViewModel}">
                <local:IconView />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

</UserControl>

注意DataTemplate告诉ItemsControl在ItemsSource列表中看到IconControlViewModel时要呈现的内容。这就是我使用MVVM模式设计它的方法。我希望这有帮助,如果你需要澄清我的答案,或者它已经结束了,请告诉我。

干杯, 埃里克