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

关键的见解是创建一个定义上下文菜单的&lt;Style&gt;, 然后将该样式附加到目标元素,该元素连接上下文 菜单。 这会将上下文菜单转换为一个可视树,该树与您想要的默认 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 标记 HierarchicalDataTemplateStyleContextMenu 标记之后)。它起作用的原因是因为将 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中 根据使用该模板的控件的不同而设置不同的图片内容。的主要内容,如果未能解决你的问题,请参考以下文章

WPF 在datagrid模板列中添加用户控件,在后台如何快速的检索到该控件。急!!!

WPF - 根据项目模板更改组合框样式

WPF 控件模板不根据依赖属性绑定值更改

WPF 弹出窗口:如何为弹出窗口制作可重复使用的模板?

C#,WPF使用word模板导出word文档

WPF - 如何结合 DataTrigger 和 Trigger?