我的应用程序中有一些列表框,其中包含电话簿的联系人。我希望所有这些列表框都有一个数据模板作为它们的itemstemplates,其中包含一些功能,如编辑、删除和查看,如下代码所示:
<DataTemplate x:Key="ContactItemTemplate">
<TextBlock Foreground="Black" Background="{StaticResource DataTemplateBackgroundBrush}" Padding="5,10" Margin="4,3">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} {1}">
<Binding Path="FirstName"/>
<Binding Path="LastName"/>
</MultiBinding>
</TextBlock.Text>
<TextBlock.ContextMenu>
<ContextMenu FontFamily="B Yekan">
<MenuItem Header="Edit" Click="btn_EditContact_Click"/>
<MenuItem Header="Delete" Click="btn_DeleteContact_Click"/>
<MenuItem Header="View" Click="btn_EditContact_Click"/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
它不能作为样式写入ResourceDictionary并添加到控件中,因为EventHandler不能在ResourceDictionary中显示。因此,一种方法是复制此模板以及每个窗口/页面中具有如下联系人列表框的处理程序:
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Styles/Controls_Style.xaml"/>
</ResourceDictionary.MergedDictionaries>
<DataTemplate x:Key="AttachmentsTemplate">
<Border Height="150" Width="120" BorderThickness="1" BorderBrush="{StaticResource DefaultBorderBrush}" Margin="2">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding Title}" HorizontalAlignment="Center" VerticalAlignment="Bottom" TextWrapping="WrapWithOverflow"/>
<Image Grid.Row="1" Source="{Binding Image}" Margin="5,0"/>
</Grid>
</Border>
</DataTemplate>
</ResourceDictionary>
</Page.Resources>
有没有其他方法可以让我只编写一次具有某些功能的数据模板,然后在任何需要的地方使用它?我应该写一个用户控件而不是一个数据模板吗?
最佳答案
只要事件处理程序是字典的一部分,就可以在字典中包含它们——也就是说,字典后面有一些代码。这类似于Page
s和UserControl
s;您需要添加一个x:Class
属性。例如,styles.xml可能如下所示:
<ResourceDictionary
x:Class="WPF.Styles"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1">
<DataTemplate x:Key="ContactItemTemplate" DataType="local:Person">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
Foreground="Black"
Background="Yellow"
Padding="5,10"
Margin="4,3"
Text="{Binding Name}"
>
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="Edit!" Click="btn_EditContact_Click"/>
<MenuItem Header="Delete!" Click="btn_DeleteContact_Click"/>
<MenuItem Header="View!" Click="btn_EditContact_Click"/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
<Button
Grid.Column="1"
Content="Edit"
Click="btn_EditContact_Click"/>
</Grid>
</DataTemplate>
</ResourceDictionary>
…带有相应的styles.cs(请注意
partial
):public sealed partial class Styles
{
private void btn_EditContact_Click(object sender, EventArgs args)
{
Debug.WriteLine(args);
}
private void btn_DeleteContact_Click(object sender, EventArgs args)
{
Debug.WriteLine(args);
}
}
在我的窗户里,像这样的东西:
<Grid.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Styles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Grid.Resources>
...
<ItemsControl
ItemsSource="{Binding People}"
Grid.Row="3"
ItemTemplate="{StaticResource ContactItemTemplate}" />
为了完整性,模型对象:
public class Person
{
public string Name { get; }
public Person(string name)
{
Name = name;
}
}
…和
ItemsSource
:public Person[] People { get; } =
{
new Person("Donald Duck"),
new Person("Mickey Mouse"),
new Person("Darth Vader"),
};
一般来说,这很好——例如,单击按钮,调用
btn_EdxtContact_Click
。不幸的是,你的场景中包含TextBox
的上下文菜单有一个问题;details and possible workarounds in this post。
更新:在上下文菜单和模板上
一小部分附加信息:this article上的评论有一些关于
ContextMenu
模板的讨论,可能会有启发性。…而且one more
TextBox
ContextMenu
link可能会被证明是有用的。关于c# - 如何编写具有某些功能的DataTemplate作为资源,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35012679/