2011-09-16 22 views
11

Vi en línea 2 enfoques diferentes para mejorar un IValueConverter. Uno de ellos extendió un ValueConverter desde MarkupExtension, el otro desde DependencyObject. No puedo extenderme de ambos, así que me pregunto si alguien es mejor que el otro.IValueConverter mejorado - ¿MarkupExtension u DependencyObject?

+0

Supongo que depende de lo que está tratando de lograr. ¿Puedes agregar más detalles? –

Respuesta

33

Derivado de cada uno le da diferentes tipos de potencia y flexibilidad:

  • Derivado MarkupExtension le permite utilizar el convertidor de valores sin que sea un recurso estático, como se describe a continuación:

    public class DoubleMe : MarkupExtension, IValueConverter 
    { 
        public override object ProvideValue(IServiceProvider serviceProvider) 
        { 
         return this; 
        } 
        public object Convert(object value, /*rest of parameters*/) 
        { 
         if (value is int) 
         return (int)(value) * 2; //double it 
         else 
         return value.ToString() + value.ToString(); 
        } 
        //... 
    } 
    

    En XAML, puede usarlo directamente sin crear un StaticResource:

    <TextBlock Text="{Binding Name, Converter={local:DoubleMe}}"/> 
    <TextBlock Text="{Binding Age, Converter={local:DoubleMe}}"/> 
    

    Este código es muy útil cuando se depura, ya que solo puede escribir local:DebugMe y luego puede depurar el DataContext del control en el que lo usa.

  • Derivado DependencyObject le permite a configurar el convertidor de valores con algunas preferencias de una manera más expresiva, como se describe a continuación:

    public class TruncateMe : DependencyObject, IValueConverter 
    { 
        public static readonly DependencyProperty MaxLengthProperty = 
         DependencyProperty.Register("MaxLength", 
                 typeof(int), 
                 typeof(TruncateMe), 
                 new PropertyMetadata(100)); 
        public int MaxLength 
        { 
         get { return (int) this.GetValue(MaxLengthProperty); } 
         set { this.SetValue(MaxLengthProperty, value); } 
        } 
    
        public object Convert(object value, /*rest of parameters*/) 
        { 
         string s = value.ToString(); 
         if (s.Length > MaxLength) 
          return s.Substring(0, MaxLength) + "..."; 
         else 
          return s; 
        } 
        //... 
    } 
    

    En XAML, puede utilizar directamente como:

    <TextBlock> 
        <TextBlock.Text> 
         <Binding Path="FullDescription"> 
          <Binding.Converter> 
          <local:TruncateMe MaxLength="50"/> 
          </Binding.Converter> 
         </Binding> 
        </TextBlock.Text> 
    

    ¿Qué hace? Trunca la cadena FullDescription si es más de 50 caracteres!

@crazyarabian comentó que:

Su declaración "Derivado de DependencyObject le permite configurar el convertidor de valores con algunas preferencias de una manera más expresiva" no es exclusivo de DependencyObject como se puede crear la misma propiedad MaxLength en una MarkupExtension que da como resultado <TextBlock Text="Binding Age, Converter={local:DoubleMe, MaxLength=50}}"/>. Yo diría que una MarkupExtension es más expresiva y menos detallada.

Eso es cierto. Pero eso no es vinculable; es decir, cuando se derivan de MarkupExtension, entonces no se puede hacer:

MaxLength="{Binding TextLength}" 

Pero si usted deriva su convertidor de DependencyObject, a continuación, puede hacer lo anterior. En ese sentido, es más expresivo en comparación con MarkupExtension.

Tenga en cuenta que la propiedad de destino debe ser DependencyProperty para Binding para que funcione.MSDN says,

  • Cada unión tiene típicamente estos cuatro componentes: un objeto de unión a la diana , una propiedad objetivo, un origen de enlace, y un camino para el valor en el origen de enlace de usar. Por ejemplo, si se desea enlazar el contenido de un cuadro de texto de la propiedad Name de un objeto empleado, su objeto de destino es del cuadro de texto, la propiedad objetivo la propiedad Text, el valor a utilizar es Nombre y el objeto de origen es el objeto de empleado .

  • La propiedad de destino debe ser una propiedad de dependencia.

+0

Vi el proyecto Converters de Kent Boogaart en Codeplex extendiendo todos los IValueConverter que escribió desde DependencyObject. http://wpfconverters.codeplex.com/SourceControl/changeset/view/61942# – michael

+0

@Nawaz Su afirmación "Derivar de' DependencyObject' le permite configurar el convertidor de valores con algunas preferencias de una manera más expresiva "no es exclusivo de 'DependencyObject' ya que puede crear la misma propiedad' MaxLength' en '' MarkupExtension' que da como resultado ''. Yo diría que un 'MarkupExtension' es más expresivo y menos detallado. – sellmeadog

+0

@crazyarabian: Sí. Puedes hacer eso, pero eso no es vinculable. No puede hacer 'MaxLength =" {Binding TextLength} "'. – Nawaz

3

Ya que es my library que estás citando como ejemplo de convertidores que se extienden DependencyObject, creo que es apropiado para explicar yo.

De hecho, comencé simplemente implementando IValueConverter con Object como mi clase base. La única razón por la que cambié a la extensión DependencyObject fue para permitir una técnica, iniciada por Josh Smith, llamada , bifurcación virtual. Puede leer sobre esa técnica here.

Suponga que quiere hacer algo como esto:

<UserControl.Resources> 
    <con:CaseConverter Casing="{Binding SomeProperty}"/> 
</UserControl.Resources> 

esto no funcionará porque los recursos no son parte del árbol visual, por lo que la unión se producirá un error. La bifurcación virtual ataca este pequeño dilema, permitiéndote realizar tal enlace. Sin embargo, todavía se basa, al igual que cualquier otra vinculación de WPF, en que el objetivo sea DependencyObject. Por lo tanto, si simplemente implementé IValueConverter sin extender DependencyObject, no podrá utilizar ramas virtuales.

Ahora, si soy completamente honesto, no estoy seguro de que todavía haría esto si tuviera mi tiempo de nuevo. Nunca en realidad tenía para usar una rama virtual, solo quería habilitar el escenario. Incluso puedo cambiar esto en una versión futura de mi biblioteca. Así que mi consejo sería adherirse a una clase base de Object (o un simple derivado de la misma) a menos que realmente piense que necesitará una bifurcación virtual.

+0

¿Funcionará esto en Silverlight también? – Shimmy

Cuestiones relacionadas