是否可以为GridViewColumn创建一个模板,而不需要固定的数据绑定? [英] Is it possible to create a template for a GridViewColumn, without fixed data binding?
问题描述
这是可能吗?
我有一个ListView,我想为这些列创建一个模板,这样我标记为cellTextBox的每个列都显示其中包含一个文本框(并且还在LostFocus事件上调用TextBox_LostFocus())。我真的想使用单个模板,而不是为每一列定义DockPanel和TextBox。但是,每列将被绑定到数据源中的另一列。
I have a ListView and I want to create a template for the columns, so that each column that I mark as a 'cellTextBox' displays with a textbox in it (and also calls the TextBox_LostFocus() on the LostFocus event). I'd really like to use a single template rather than defining a DockPanel and TextBox for every single column. However, each column is going to be bound to a different column in the data source.
换句话说,我想为GridViewColumns提供一个cookie cutter,允许我为每个人指定一个不同的绑定路径。
In other words, I'd like a "cookie cutter" for GridViewColumns that allows me to specify a different binding path for each one.
我尝试过这样的东西(除其他外),但它不起作用。
I tried something like this (among other things), but it doesn't work.
任何想法?
<Page.Resources>
<DataTemplate x:Key="cellTextBox">
<DockPanel>
<TextBox
LostFocus="TextBox_LostFocus"
Width="100"
Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=DisplayMemberBinding}"
/>
</DockPanel>
</DataTemplate>
</Page.Resources>
<StackPanel>
<ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled"
HorizontalAlignment="Stretch"
ItemsSource="{Binding Tables[0]}"
Width="Auto"
x:Name="Service_Tasks">
<ListView.View>
<GridView>
<GridViewColumn Width="120" CellTemplate="{StaticResource cellTextBox}" DisplayMemberBinding={Binding Path=Field1} Header="Field1" />
<GridViewColumn Width="120" CellTemplate="{StaticResource cellTextBox}" DisplayMemberBinding={Binding Path=Field2} Header="Field2" />
<GridViewColumn Width="120" CellTemplate="{StaticResource cellTextBox}" DisplayMemberBinding={Binding Path=Field3} Header="Field3" />
<GridViewColumn Width="120" CellTemplate="{StaticResource cellTextBox}" DisplayMemberBinding={Binding Path=FieldN} Header="FieldN" />
<!-- ... other columns ... -->
</GridView>
</ListView.View>
</ListView>
</StackPanel>
编辑 - 我以为我会分享@HB的Visual Basic翻译的解决方案,对我有用。也许这将有助于别人。
EDIT - I thought I would share the Visual Basic translation of @H.B.'s solution, which worked for me. Perhaps this will help out someone else.
Imports System.Windows.Markup
Public Class TemplateBuilderExtension : Inherits StaticExtension
Dim _path As String
Shared _tagpath As String
'Private TagPath As String
Shared Property TagPath As String
Get
TagPath = _tagpath
End Get
Private Set(ByVal value As String)
_tagpath = value
End Set
End Property
Property Path As String
Get
Path = _path
End Get
Set(ByVal value As String)
_path = value
End Set
End Property
Public Overrides Function ProvideValue(ByVal serviceProvider As System.IServiceProvider) As Object
TagPath = Path
Dim resourceExt = New StaticResourceExtension("TemplateBuilder_BaseTemplate")
'Dim baseTemplate As DataTemplate = DirectCast(resourceExt.ProvideValue(serviceProvider), DataTemplate)
ProvideValue = DirectCast(resourceExt.ProvideValue(serviceProvider), DataTemplate)
End Function
Public Sub New()
MyBase.new()
End Sub
Public Sub New(ByVal Path As String)
Me.Path = Path
End Sub
End Class
Public Class TemplateBuilderTagExtension : Inherits MarkupExtension
Public Sub New()
MyBase.New()
End Sub
Public Overrides Function ProvideValue(ByVal serviceProvider As System.IServiceProvider) As Object
ProvideValue = New Binding(TemplateBuilderExtension.TagPath)
End Function
End Class
显然,XAML是一样的,无论如何。
Obviously, the XAML is the same, regardless.
不要忘记添加以下命名空间引用您的根级标签:
Do not forget to add the following namespace reference to your root-level tag:
xmlns:me =clr-namespace:W pfApplication1
,替换 WpfApplication
,无论您的应用程序的根命名空间是什么(这可以在应用程序的属性中找到)。
xmlns:me="clr-namespace:WpfApplication1"
, replacing WpfApplication
with whatever your application's root namespace is (this can be found in your application's properties).
再次感谢@HB!
推荐答案
现在我可以想到的唯一方法是内联这个正在使用标记扩展程序,因为您尝试传递多个值一个属性。
The only method i can think of right now to inline this is using markup-extensions as you try to pass more than one value to one property.
将变量数据导入模板似乎是不平凡的,而使用静态属性的以下方法是相当的黑客,也许你可以想到一些东西更好:
Getting variable data into the template seems to be non-trivial though and the following approach using a static property is quite the hack, maybe you can think of something better:
<ListView ItemsSource="{Binding Data}">
<ListView.Resources>
<!-- x:Shared="False" because otherwise the Tag extension is only evaluated the first time the resource is accessed -->
<DataTemplate x:Shared="false" x:Key="TemplateBuilder_BaseTemplate">
<TextBox Text="{me:TemplateBuilderTag}" Width="100" LostFocus="TextBox_LostFocus" />
</DataTemplate>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn CellTemplate="{me:TemplateBuilder Name}" />
<GridViewColumn CellTemplate="{me:TemplateBuilder Occupation}" />
</GridView>
</ListView.View>
</ListView>
public class TemplateBuilderExtension : MarkupExtension
{
public string Path { get; set; }
public TemplateBuilderExtension() { }
public TemplateBuilderExtension(string path)
{
Path = path;
}
// Here be dirty hack.
internal static string TagPath { get; private set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
TagPath = Path;
var resourceExt = new StaticResourceExtension("TemplateBuilder_BaseTemplate");
// This line causes the evaluation of the Tag as the resource is loaded.
var baseTemplate = resourceExt.ProvideValue(serviceProvider) as DataTemplate;
return baseTemplate;
}
}
public class TemplateBuilderTagExtension : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
return new Binding(TemplateBuilderExtension.TagPath);
}
}
我尝试使用自定义服务提供商获取资源,但不幸的是它没有到达标签的 ProvideValue
,这将是更好的方法来获取路径。
I tried to use a custom service provider when getting the resource but unfortunately it did not arrive in ProvideValue
of the tag, that would have been a better way to get the path accross.
您当然可以在 TemplateBuilderExtension
中从头开始动态创建模板,这样就不会遇到这样的问题。
You could of course create the template dynamically from scratch in the TemplateBuilderExtension
, that way you will not run into such issues.
这篇关于是否可以为GridViewColumn创建一个模板,而不需要固定的数据绑定?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!