WPF如何在模板的Trigger中 根据使用该模板的控件的不同而设置不同的图片内容。
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF如何在模板的Trigger中 根据使用该模板的控件的不同而设置不同的图片内容。相关的知识,希望对你有一定的参考价值。
<DataTemplate x:Key="DataTemplate_Zoom">
<Grid Width="20" Height="20">
<Image x:Name="ImageZoom" Source="TemplateBinding RadioButton.Content" Stretch="Fill">
</Image>
</Grid>
<DataTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Source" Value="Images/diszoom.png" TargetName="ImageZoom"/>
</Trigger>
<Trigger Property="IsEnabled" Value="True">
<Setter Property="Source" Value="Images/enzoom.png" TargetName="ImageZoom"/>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
为了方便看xml代码,我不光贴出来模板代码还附上截图方便看关键字。
功能描述:我有很多个RadioButton,每个都有Enable和disable状态的图片,我在之前的做法是为每个RadioButton都写了一个模板,在触发器事件中分别制定了2个状态的图片路径。这样做没有问题。
现在的问题是:
我想让所有的RadioButton共用一个模板,但是无法解决这个触发器里的图片路径根据不同的RadioButton获取不同的路径的问题。而且Trigger里无法用TemplateBinding. 想自己写一个类继承RadioButton然后重写Enable改变的方法,但是WPF里不像WinForm,没有对应的可以重写, 请高手来帮忙!!
首先 我写了一个继承RadioButton的类。主要是加了两个string类型的字段,用来存放RadioButton 两个状态下的图片路径
public class MyRadioButton:RadioButton
public string EnableImaUri
get return (string)GetValue(EnableImaUriProperty);
set SetValue(EnableImaUriProperty, value);
public static readonly DependencyProperty EnableImaUriProperty = DependencyProperty.Register("EnableImaUri", typeof(string), typeof(MyRadioButton), null);
public string DisEnableImaUri
get return (string)GetValue(DisEnableImaUriProperty);
set SetValue(DisEnableImaUriProperty, value);
public static readonly DependencyProperty DisEnableImaUriProperty = DependencyProperty.Register("DisEnableImaUri", typeof(string), typeof(MyRadioButton), null);
然后在页面前台放上一个button和radiobutton。思路是通过radiobutton的IsEnabledChanged事件来改变Image的source。由于第一次加载时是不触发这个事件的,所以image还是要在前台写一遍默认路径。
<local:MyRadioButton x:Name="myRbtn1" EnableImaUri="ranbo.jpg" DisEnableImaUri="shafa.jpg" IsEnabledChanged="myRbtn1_IsEnabledChanged">
<Image Width="100" Height="100" Source="/WpfApplication1;component/Images/shafa.jpg"/>
</local:MyRadioButton>
<Button Width="50" Height="20" Click="Button_Click" Margin="10"/>
然后在后台处理逻辑:
private void Button_Click(object sender, RoutedEventArgs e)
if (myRbtn1.IsEnabled == true)
myRbtn1.IsEnabled = false;
else
myRbtn1.IsEnabled = true;
private void myRbtn1_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
MyRadioButton rBtn = sender as MyRadioButton;
Image img = rBtn.Content as Image; if (img == null) return;
if (rBtn.IsEnabled == true)
Uri uri = new Uri("/Images/" + rBtn.EnableImaUri, UriKind.Relative);
img.Source = new BitmapImage(uri);
else
Uri uri = new Uri("/Images/" + rBtn.DisEnableImaUri, UriKind.Relative);
img.Source = new BitmapImage(uri);
OK了!!!有什么问题欢迎继续提问 ^ ^ 参考技术A 每个RadioButton一个模板显然太累赘,没那个必要。
你可以做一个UserControl,在里面放一个RadioButton,初始化时可以给他的Tag打上标记,或者给这个UserControl加一个Id,当发出Enable或者Disable事件时,可以根据此Id获知是哪个RadionButton触发了事件,相应的就可以用switch或者数组来获取图片。
方法很多,具体操作还得看你的具体需求。
如何在 wpf 的分层数据模板中显示树视图项的上下文菜单
【中文标题】如何在 wpf 的分层数据模板中显示树视图项的上下文菜单【英文标题】:How to display context menu for treeview item in a hierarchial data template in wpf 【发布时间】:2012-11-05 10:31:17 【问题描述】:如何使用分层数据模板在 wpf 中显示树视图项的上下文菜单?如何仅为 CountryTemplate 显示上下文菜单:
<HierarchicalDataTemplate x:Key="DispTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Binding Path=Label" Style="StaticResource TreeTextStyle" ToolTip="Binding Path=Description" Tag="Binding Path=Tag">
</TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="BuildingTemplate" ItemsSource="Binding Path=Building" ItemTemplate="StaticResource BuildingTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Binding Path=Label" Style="StaticResource TreeTextStyle" ToolTip="Binding Path=Description"/>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="CityTemplate" ItemsSource="Binding Path=City" ItemTemplate="StaticResource CityTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Binding Path=Label" Style="StaticResource TreeTextStyle" ToolTip="Binding Path=Description"/>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="CountryTemplate" ItemsSource="Binding Path=Country" ItemTemplate="StaticResource CountryTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Binding Path=RootName" Style="StaticResource TreeTextStyle" ToolTip="Binding Path=Description"/>
</StackPanel>
</HierarchicalDataTemplate>
【问题讨论】:
【参考方案1】:您还可以将ContextMenu
添加到数据模板中的任何可视子项,例如:
<HierarchicalDataTemplate x:Key="CountryTemplate" ItemsSource="Binding Path=Country" ItemTemplate="StaticResource CountryTemplate">
<StackPanel Orientation="Horizontal">
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="Header" Command="Binding Command"/> <!--This command should be in the data context (each country item)-->
</ContextMenu>
</StackPanel.ContextMenu>
<TextBlock Text="Binding Path=RootName" Style="StaticResource TreeTextStyle" ToolTip="Binding Path=Description"/>
</StackPanel>
</HierarchicalDataTemplate>
【讨论】:
如何绑定到视图模型根目录中定义的命令。到目前为止 FindAncestor 方法不起作用。你能给我举个例子吗? 在我无法轻松访问视图模型以进行绑定的情况下,我尝试使用此 FindAncestor 绑定:Command="Binding DataContext.Command, RelativeSource=RelativeSource FindAncestor, AncestorType= x:Type MainWindow",一般主窗口的datacontext有根视图模型,有你想要的命令。 这不适用于上下文菜单,因为它不是可视化树的一部分。 是的,你是对的,那么你应该从你的视图模型中发出命令。也许使用一种消息(mvvm light 或由您自己实现)或为您的所有视图模型层次结构引发事件,这是一种复杂的方式。 是的,即使是像这样的小东西 XAML 也是一个真正的痛苦。我必须想出超出正常范围的解决方案。【参考方案2】:上下文菜单无法正常工作的原因之一是,默认情况下,它们位于与其他所有内容不同的可视化树中,因此无法找到 DataContext
。
关键的见解是创建一个定义上下文菜单的
<Style>
, 然后将该样式附加到目标元素,该元素连接上下文 菜单。 这会将上下文菜单转换为一个可视树,该树与您想要的默认DataContext
对齐。
首先,创建样式:
<UserControl.Resources>
<ResourceDictionary>
<!-- For the context menu to work, we must shift it into a style, which means that the context menu is now in a
visual tree that is more closely related to the current data context. All we have to do then is set the style,
which hooks up the context menu. -->
<Style x:Key="ContextMenuStyle" TargetType="x:Type StackPanel">
<Setter Property="ContextMenu" Value="DynamicResource TreeViewContextMenu"/>
</Style>
<ContextMenu x:Key="TreeViewContextMenu">
<MenuItem Header="Test" Command="Binding RelativeSource=RelativeSource FindAncestor, AncestorType=x:Type UserControl, Path=DataContext.CmdDisplayDetailsGraph"/>
</ContextMenu>
然后,将上下文菜单挂在您想要的任何位置,而不会遇到由不同视觉树引起的问题。
示例 1:
<HierarchicalDataTemplate DataType="x:Type snapshot:Details" ItemsSource="Binding DetailsList">
<StackPanel Orientation="Vertical" Style="StaticResource ContextMenuStyle">
<ContentPresenter Content="Binding" ContentTemplate="Binding View.DefaultDataRowTemplate" />
</StackPanel>
示例 2:
<DataTemplate DataType="x:Type snapshot:InstrumentDetails">
<StackPanel Orientation="Vertical" Style="StaticResource ContextMenuStyle">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Center">
【讨论】:
【参考方案3】:<HierarchicalDataTemplate x:Key="CountryTemplate" ItemsSource="Binding Path=Country" ItemContainerStyle="StaticResource CountryTemplateItemContainerStyle" ItemTemplate="StaticResource CountryTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Binding Path=RootName" Style="StaticResource TreeTextStyle" ToolTip="Binding Path=Description" />
</StackPanel>
</HierarchicalDataTemplate>
<Style x:Key="CountryTemplateItemContainerStyle" TargetType="x:Type TreeViewItem">
<Setter Property="ContextMenu" Value="DynamicResource TreeViewContextMenu"/>
</Style>
<ContextMenu x:Key="TreeViewContextMenu">
<MenuItem .../>
</ContextMenu>
如您所见,您可以在 HierarchicalDataTemplate 的 Itemcontainerstyle 中添加上下文菜单
【讨论】:
这对我来说非常有用,而且,我喜欢 ContextMenu 是如何在项目附近定义的。 这对我有用。为了避免编译错误,我不得不交换块(确保 XAML 标记HierarchicalDataTemplate
在 Style
和 ContextMenu
标记之后)。它起作用的原因是因为将 ContextMenu 转换为样式会将所有内容转换为更密切相关的可视化树,这意味着可以轻松找到 DataContext。【参考方案4】:
基本上我想出了这个
<HierarchicalDataTemplate x:Key="ChildTemplate">
<StackPanel Orientation="Horizontal">
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="Copy" CommandParameter="Binding CopyTag">
</MenuItem>
<MenuItem Header="Paste" CommandParameter="Binding PasteTag">
</MenuItem>
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Command" Value="Binding RelativeSource=RelativeSource FindAncestor, AncestorType=x:Type UserControl, Path=DataContext.CopyPaste"/>
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</StackPanel.ContextMenu>
<Image Source="/Images/Child.png" Stretch="None" VerticalAlignment="Center" HorizontalAlignment="Center" Style="StaticResource TreeIconStyle"/>
<TextBlock Text="Binding Path=Label" Style="StaticResource TreeTextStyle" ToolTip="Binding Path=Description" Tag="Binding Path=Tag">
</TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
并具有单独的复制和粘贴参数,以区分单个命令中的复制和粘贴。
【讨论】:
以上是关于WPF如何在模板的Trigger中 根据使用该模板的控件的不同而设置不同的图片内容。的主要内容,如果未能解决你的问题,请参考以下文章