wpf xaml data-binding datatemplate

wpf - ¿Es posible crear una plantilla para un GridViewColumn, sin enlace de datos fijo?



xaml data-binding (1)

El único método en el que puedo pensar ahora para incorporar esto es usar markup-extensions mientras intentas pasar más de un valor a una propiedad.

Sin embargo, la obtención de datos variables en la plantilla parece no ser trivial, y el siguiente enfoque con una propiedad estática es bastante complicado, tal vez se te ocurra algo mejor:

<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); } }

Traté de usar un proveedor de servicios personalizado al obtener el recurso, pero desafortunadamente no llegó en ProvideValue de la etiqueta, esa habría sido una mejor manera de cruzar la ruta.

Por supuesto, puede crear la plantilla dinámicamente desde cero en TemplateBuilderExtension , de esa manera no se encontrará con tales problemas.

es posible?

Tengo un ListView y quiero crear una plantilla para las columnas, de modo que cada columna que marque como ''cellTextBox'' se muestre con un cuadro de texto (y también llame a TextBox_LostFocus () en el evento LostFocus). Realmente me gustaría utilizar una única plantilla en lugar de definir un DockPanel y un TextBox para cada columna. Sin embargo, cada columna se vinculará a una columna diferente en la fuente de datos.

En otras palabras, me gustaría un "cortador de galletas" para GridViewColumns que me permita especificar una ruta de enlace diferente para cada uno.

Intenté algo como esto (entre otras cosas), pero no funciona.

¿Algunas ideas?

<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>

EDITAR - Pensé que compartiría la traducción de Visual Basic de la solución de @ HB, que funcionó para mí. Quizás esto ayudará a alguien más.

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

Obviamente, el XAML es el mismo, independientemente.

No olvide agregar la siguiente referencia de espacio de nombres a su etiqueta de nivel raíz:

xmlns:me="clr-namespace:WpfApplication1" , reemplazando WpfApplication con el espacio de nombres raíz de la aplicación (esto se puede encontrar en las propiedades de la aplicación).

Gracias de nuevo @HB!