是否可以为GridViewColumn创建一个模板,而不需要固定的数据绑定? [英] Is it possible to create a template for a GridViewColumn, without fixed data binding?

查看:129
本文介绍了是否可以为GridViewColumn创建一个模板,而不需要固定的数据绑定?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是可能吗?

我有一个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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆