wpf - La encuadernación como recurso
xaml wpf-controls (2)
Aquí hay dos maneras de no hacer exactamente lo que quieres:
1. Usando una extensión de marcado personalizado
Se saltan todos los nullchecks, etc. para que sea breve.
using System;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;
public class BindingDefinition
{
public PropertyPath Path { get; set; }
public BindingMode Mode { get; set; }
}
[MarkupExtensionReturnType(typeof(BindingExpression))]
public class ApplyBindingDefinition : MarkupExtension
{
public BindingDefinition Definition { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
var binding = new Binding
{
Path = this.Definition.Path,
Mode = this.Definition.Mode
};
return binding.ProvideValue(serviceProvider);
}
}
<Window.Resources>
<local:BindingDefinition x:Key="MyProperty"
Mode="TwoWay"
Path="MyProperty" />
</Window.Resources>
<TextBox>
<TextBox.Text>
<!-- using element style here as the parser chokes on parsing nested markupextensions -->
<local:ApplyBindingDefinition Definition="{StaticResource MyProperty}" />
</TextBox.Text>
</TextBox>
2. Convertir el PropertyPath en un recurso
Puede o no puede ser suficiente para sus necesidades.
<Window.Resources>
<PropertyPath x:Key="MyPropertyPath">MyProperty</PropertyPath>
</Window.Resources>
...
<TextBox Text="{Binding Path={StaticResource MyPropertyPath}}" />
¿Puedo definir un Binding
como un Resource
y luego reutilizarlo con diferentes propiedades de Controls
?
Ejemplo:
Unión:
<Window.Resources>
<Binding x:Key="MyBinding" Path="MyProperty" Mode="TwoWay" />
</Window.Resources>
Reutilizar en XAML:
<TextBox Text="{StaticResource MyBinding}" />
Después de declarar el Binding
como arriba, recibí el error:
"El nombre ''InitializeComponent'' no existe en el contexto actual"
¿Hay alguna forma de reutilizar el mismo Binding
en diferentes contextos?
La respuesta directa a su pregunta es "sí, puede definir un enlace como un recurso". El problema aquí es, ¿cómo hacer uso de él? Una posibilidad es crear una clase de extensión que extraiga el enlace de los recursos y la aplique:
public class BindingResourceExtension : StaticResourceExtension
{
public BindingResourceExtension() : base() { }
public BindingResourceExtension(object resourceKey) : base(resourceKey) { }
public override object ProvideValue(IServiceProvider serviceProvider)
{
var binding = base.ProvideValue(serviceProvider) as BindingBase;
if (binding != null)
return binding.ProvideValue(serviceProvider);
else
return null; //or throw an exception
}
}
Ejemplo de uso:
<Window.Resources>
<ResourceDictionary>
<Binding x:Key="MyBinding" Path="MyProperty" Mode="TwoWay" />
</ResourceDictionary>
</Window.Resources>
(...)
<TextBox Text="{ns:BindingResource MyBinding}" />
¿Se puede utilizar esta solución en MultiBinding
?
Sí puede:
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="First: {0}, Second: {1}">
<Binding Path="SomeProperty" />
<ns:BindingResource ResourceKey="MyBinding" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
Sin embargo, hay un inconveniente de esto: aunque todo funcionará en tiempo de ejecución, el Diseñador XAML se quejará de que BindingResourceExtension
no es del tipo adecuado para MultiBinding.Bindings
en la colección MultiBinding.Bindings
. Pero, afortunadamente, existe una solución rápida: ¡simplemente use StaticResourceExtension
en StaticResourceExtension
lugar! Así que esto, aunque es funcionalmente equivalente en tiempo de ejecución, será aceptado por el diseñador:
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="First: {0}, Second: {1}">
<Binding Path="SomeProperty" />
<StaticResource ResourceKey="MyBinding" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>