WPF 样式/控件模板重用
我是 WPF 新手,我想知道如何重用一些我必须避免重复的烦人的 xaml。
<Button Cursor="Hand" HorizontalAlignment="Left" Margin="0,0,0,0" x:Name="MyButton" Style="{StaticResource ButtonTemplate}" Width="286" Content="hi!" Focusable="False" IsTabStop="False"/>
<Button Cursor="Hand" HorizontalAlignment="Left" Margin="0,0,0,0" x:Name="MyButton2" Style="{StaticResource ButtonTemplate}" Width="286" Content="hi 2!" Focusable="False" IsTabStop="False"/>
我真的很想使用类似这样的模板:
<Style TargetType="{x:Type Button}" x:Key="ButtonTemplate">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid x:Name="btGrid">
<Path Cursor="Hand" HorizontalAlignment="Left" Stretch="Fill" Stroke="{x:Null}" Opacity="0" x:Name="path"/>
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" RecognizesAccessKey="True" Visibility="Hidden" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Top"/>
</Grid>
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="Button.PreviewMouseLeftButtonDown">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard SlipBehavior="Slip" BeginTime="00:00:00">
<MediaTimeline Source="{Binding StringFormat={}, Path=Name}" Storyboard.TargetName="{Binding StringFormat={}_wma, Path=Name}"/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="{Binding StringFormat=key{}, Path=Name}" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>
Visible
</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Button.PreviewMouseLeftButtonUp">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="{Binding StringFormat=key{}, Path=Name}" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>
Hidden
</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<Trigger Property="IsFocused" Value="True"/>
<Trigger Property="IsDefaulted" Value="True"/>
<Trigger Property="IsMouseOver" Value="True"/>
<Trigger Property="IsPressed" Value="True"/>
<Trigger Property="IsEnabled" Value="False"/>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
并且我希望 {Binding StringFormat={}, Path=Name} 指向按钮的名称,例如“MyButton”、“MyButton2”等。
当我运行此代码时我收到错误“无法冻结此 Storyboard 时间线树以便跨线程使用。” :/我明白这是因为我在故事板中使用了绑定,对吗?我不知道该怎么做才能完成这项工作。
另外,我还想将图像的 ToggleVisibility 设为模板,它接受一次“可见”值和一次“隐藏”值。 提前致谢!
I'm new to WPF, and I would like to know how to reuse some annoying xaml I have to avoid duplicating.
<Button Cursor="Hand" HorizontalAlignment="Left" Margin="0,0,0,0" x:Name="MyButton" Style="{StaticResource ButtonTemplate}" Width="286" Content="hi!" Focusable="False" IsTabStop="False"/>
<Button Cursor="Hand" HorizontalAlignment="Left" Margin="0,0,0,0" x:Name="MyButton2" Style="{StaticResource ButtonTemplate}" Width="286" Content="hi 2!" Focusable="False" IsTabStop="False"/>
I'd really like to use something like this template:
<Style TargetType="{x:Type Button}" x:Key="ButtonTemplate">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid x:Name="btGrid">
<Path Cursor="Hand" HorizontalAlignment="Left" Stretch="Fill" Stroke="{x:Null}" Opacity="0" x:Name="path"/>
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" RecognizesAccessKey="True" Visibility="Hidden" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Top"/>
</Grid>
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="Button.PreviewMouseLeftButtonDown">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard SlipBehavior="Slip" BeginTime="00:00:00">
<MediaTimeline Source="{Binding StringFormat={}, Path=Name}" Storyboard.TargetName="{Binding StringFormat={}_wma, Path=Name}"/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="{Binding StringFormat=key{}, Path=Name}" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>
Visible
</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Button.PreviewMouseLeftButtonUp">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="{Binding StringFormat=key{}, Path=Name}" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>
Hidden
</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<Trigger Property="IsFocused" Value="True"/>
<Trigger Property="IsDefaulted" Value="True"/>
<Trigger Property="IsMouseOver" Value="True"/>
<Trigger Property="IsPressed" Value="True"/>
<Trigger Property="IsEnabled" Value="False"/>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And I'd like the {Binding StringFormat={}, Path=Name} to point button's name, e.g. "MyButton", "MyButton2", etc.
When I run this code I get the error "Cannot freeze this Storyboard timeline tree for use across threads." :/ I understand this is because I use binding in a storyboard, correct? I don't know what to do to make this work.
Also, I'd like to make the ToggleVisibility of the image a template as well, that accepts once "Visible" and once "Hidden" values.
Thanks in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的,创建一个目标类型为按钮的样式就可以了。
提示:
在代码的资源部分下编写所有样式信息(例如边框、背景、模板等)并将它们应用到控件上始终是一个好习惯。它会提供良好的可读性。哈:)
Yeah creating a style with target type to as button would do the trick.
Tip:
It is always a good practice to write all the styling informations such as border, background, templates, etc., under the resource section of your code and apply them on the controls. It'll give good readability.HTH :)
您也可以随时在样式中定义除 Template 之外的属性。
这使得你的代码看起来像
You could always define properties other than Template in your style too.
Which makes your code look like