2010-08-24 5 views
1

Q: Pourquoi mon UserControl TextBox personnalisé utilisant MultiBinding et IMultiValueConverter obtient-il sa méthode Convert() appelée une seule fois (lors de l'instanciation)?MultiBinding et IMultiValueConverter Convert() appelé une seule fois

J'ai défini un UserControl qui nécessite une MultiBinding et un IMultiValueConverter afin de changer son comportement/présentation sur 2 indenpendant DependencyProperty.

<proj:MyControl Value="10" Digits="1" /> 

UserControl:

<UserControl x:Class="MyControl" 
      x:Name="uc" 
      ...> 

    <UserControl.Resources> 
     <conv:DecimalToStringMultiConverter x:Key="DecToString" /> 
    </UserControl.Resources> 

    [...] 

    <Grid> 
     <ctrl:VTextBox x:Name="vTb" Grid.Column="0" Margin="0,0,2,0"> 
      <ctrl:VTextBox.Text> 
       <MultiBinding Converter="{StaticResource DecToString}" UpdateSourceTrigger="LostFocus" Mode="TwoWay"> 
        <Binding ElementName="uc" Path="Value" Mode="TwoWay" /> 
        <Binding ElementName="uc" Path="Digits" Mode="TwoWay" /> 
       </MultiBinding> 
      </ctrl:VTextBox.Text> 
     </ctrl:VTextBox> 
    </Grid> 
</UserControl> 

Lors de l'exécution de l'application, les UserControls sont tous correctement instanciés. Cependant, la méthode IMultiValueConverter.Convert() est appelée seulement une fois.

l'aide d'un simple, Binding + IValueConverter avec une ConvertParameter constante a très bien fonctionné: Convert() méthode du convertisseur obtiendrait appelé chaque fois que le TextBox contenu à l'intérieur du UserControl avait sa propriété Text changé.

design changé et je devais recourir à l'aide d'un MultiBinding + IMultiValueConverter, et maintenant la méthode Convert() n'est appelée une fois, et la propriété TextBox.Text est jamais mis à jour sur l'événement LostFocus().

Ce qui donne?

Le MultiValueConverter est défini comme ci-dessous. Je viens d'enrouler IMultiValueConverter sur IValueConverter pour réutiliser le code existant.

[ValueConversion(/*sourceType*/ typeof(Decimal), /*targetType*/ typeof(string))] 
public class DecimalToStringConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value == null) 
      return "0.00"; 

     int? digits = parameter as int?; 

     if(digits == null) 
      digits = 2; 

     NumberFormatInfo nfi = (NumberFormatInfo) CultureInfo.InvariantCulture.NumberFormat.Clone(); 
     nfi.NumberGroupSeparator = " "; 
     nfi.CurrencyDecimalSeparator = "."; 
     nfi.NumberDecimalDigits = (int)digits; 

     return ((decimal)value).ToString("n", nfi); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value == null) 
      return 0.00m; 

     decimal d; 

     return decimal.TryParse((string)value, out d) ? d : 0.00m; 
    } 
} 

[ValueConversion(/*sourceType*/ typeof(Decimal), /*targetType*/ typeof(string))] 
public class DecimalToStringMultiConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
    { 
     DecimalToStringConverter conv = new DecimalToStringConverter(); 
     return conv.Convert(values[0], targetType, values.Length > 1 ? values[1] : null, culture); 
    } 

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
    { 
     DecimalToStringConverter conv = new DecimalToStringConverter(); 
     return new[] { conv.ConvertBack(value, targetTypes[0], null, culture) }; 
    } 
} 
+0

Lorsque vous exécutez ceci dans le débogueur, obtenez-vous des exceptions dans la fenêtre de sortie? – Jay

+0

Aucune exception du tout! La liaison semble bien fonctionner, mais seulement lors de l'instanciation. –

Répondre

0

Il semble que vous ayez des attentes conflictuelles concernant le comportement de mise à jour de Binding et TextBox. La seule raison pour laquelle Convert sera appelé plusieurs fois est si les valeurs de Digits ou de Value changent plusieurs fois, et rien dans votre code affiché n'indique que cela se produira. Les modifications apportées à TextBox.Text ne provoqueront pas d'appels à Convertir, mais devraient plutôt appeler ConvertBack à chaque modification + LostFocus. Est-ce que vous voyez cela lorsque vous exécutez votre code?

Vous devez également renvoyer deux valeurs, au lieu de celle qui existe actuellement, à partir de votre méthode ConvertBack afin de fournir les deux liaisons utilisées dans MultiBinding avec des valeurs.

+0

Vous avez raison. Ma compréhension est que la liaison traditionnelle fait toute modification à la propriété Text mettre à jour le DependencyProperty lié (dans ce cas, Value). Lors de la mise à jour de Value, la méthode Convert() est appelée (ce qui fait que ma formalisation personnalisée et d'autres choses ont été supprimées pour plus de simplicité dans l'exemple ci-dessus). - Cependant, MultiBinding, bien qu'il mette à jour la valeur, il ne semble pas qu'il déclenche la méthode Convert(). Comme si la liaison 2way était cassée en quelque sorte ... J'ai ajouté du code-behind pour mettre à jour Value (et utilisé la liaison OneWay à la place) et tout va bien maintenant, merci! –

Questions connexes