在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的代码
答案 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模式设计它的方法。我希望这有帮助,如果你需要澄清我的答案,或者它已经结束了,请告诉我。
干杯, 埃里克