2008-12-18 15 views
10

J'essaie d'implémenter un contrôle utilisateur wpf qui lie une zone de texte à une liste de doubles à l'aide d'un convertisseur. Comment puis-je définir l'instance du contrôle utilisateur comme paramètre du convertisseur?Quel devrait être le paramètre convertisseur pour cette liaison?

le code pour le contrôle est illustré ci-dessous

Merci

<UserControl x:Class="BaySizeControl.BaySizeTextBox" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:BaySizeControl" 
    > 
    <UserControl.Resources> 
     <local:BayListtoStringConverter x:Key="BaySizeConverter"/> 
    </UserControl.Resources> 
    <Grid> 

     <TextBox Name="Textbox_baysizes" 
        Text="{Binding RelativeSource={RelativeSource self}, 
           Path=Parent.Parent.BaySizeItemsSource, 
           Converter={StaticResource BaySizeConverter}}" 
        /> 
    </Grid> 
</UserControl> 

Répondre

8

Les paramètres sont des constantes nécessaires à votre convertisseur. Pour fournir une instance d'objet à votre convertisseur, vous pouvez utiliser MultiBinding.

Remarque: Pour que cette solution fonctionne, vous devez également modifier votre convertisseur pour implémenter IMultiValueConverter au lieu de IValueConverter. Heureusement, les modifications impliquées sont assez peu. Vous pouvez ajouter une validation pour le nombre de valeurs fournies à votre convertisseur, 2 dans votre cas.

<TextBox Name="Textbox_baysizes"> 
    <TextBox.Text> 
     <MultiBinding Converter="{StaticResource BaySizeConverter}"> 
      <Binding RelativeSource="{RelativeSource self}" Path="Parent.Parent.BaySizeItemsSource"/> 
      <Binding ElementName="Textbox_baysizes"/> 
     </MultiBinding> 
    </TextBox.Text> 
</TextBox> 
+2

Bien sûr, vous pouvez passer des références d'objet en tant que paramètres de conversion - vrai que cela doit être considéré comme une constante car WPF ne permet pas de ré-affecter le paramètre convertisseur, mais cela ne veut pas dire t être une référence d'objet! –

+0

@Frederic: Je reçois une erreur en essayant ce code. "Property 'Converter' ne supporte pas les valeurs de type 'BaySizeControl.BayListtoStringConverter'". Mon convertisseur nécessitera-t-il des modifications pour fonctionner avec cette solution? –

+0

@Daniel Paull: Cela semble fonctionner. Peux tu développer ta pensée à ce propos?merci –

1

je nommerais le contrôle et de se lier puis en utilisant ElementName:

<UserControl x:Class="BaySizeControl.BaySizeTextBox" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:BaySizeControl" 
    Name="Foobar" 
    > 
    <UserControl.Resources> 
     <local:BayListtoStringConverter x:Key="BaySizeConverter"/> 
    </UserControl.Resources> 
    <Grid> 

     <TextBox Name="Textbox_baysizes" 
        Text="{Binding RelativeSource={RelativeSource self}, 
           Path=Parent.Parent.BaySizeItemsSource, 
           Converter={StaticResource BaySizeConverter, 
           ConverterParameter={Binding ElementName=Foobar} }}" 
        /> 
    </Grid> 
</UserControl> 

Non, attendez, qui ne fonctionnera pas parce que le ConverterParameter est pas une propriété de dépendance, ni la liaison d'un DependencyObject. Une extension de balisage ReleativeSource devrait faire ce que vous voulez, mais je ne l'ai pas utilisé imbriqué dans d'autres MarkupExtension - peut-être il n'est pas bien comportés dans ce cas:

<TextBox Name="Textbox_baysizes" 
         Text="{Binding RelativeSource={RelativeSource self}, 
            Path=Parent.Parent.BaySizeItemsSource, 
            Converter={StaticResource BaySizeConverter, 
            ConverterParameter={RelativeSource self} }}" 
         /> 
+0

J'ai déjà essayé cette méthode. Le paramètre transmis est de type System.Windows.Data.RelativeSource. Pas BaySizeTextBox comme prévu. –

+0

Nous ne sommes pas après "self", essayez "{RelativeSource FindAncestor, AncestorType = {x: Type UserControl}}". –

1

J'ai eu le même problème, mais je ne peux pas utilisez MultiBindings car j'ai besoin d'implémenter correctement la méthode ConvertBack. Voici la solution que je fini par la mise en œuvre de la propriété IsChecked d'un CheckBox:

<CheckBox> 
    <CheckBox.IsChecked> 
     <Binding Converter="{StaticResource myConverter}" Path="Value"> 
      <Binding.ConverterParameter> 
       <FrameworkElement DataContext="{TemplateBinding DataContext}" /> 
      </Binding.ConverterParameter> 
     </Binding> 
    </CheckBox.IsChecked> 
</CheckBox> 

Je ne suis pas super familier avec TemplateBindings (ou quoi que ce soit WPF pour cette question), alors peut-être cela ne fonctionne que parce que mon CheckBox est dans un DataTemplate ...

+0

Après tout ce sera avec le datacontext nul. – Evgeny

11

Une autre méthode consiste à faire en sorte que votre convertisseur hérite de DependencyObject (ou FrameworkElement). Cela vous permet de déclarer les propriétés de dépendance, ce qui permet de définir ses valeurs à partir de XAML, même une liaison.

Exemple: Un convertisseur pour multiplier une valeur spécifiant le facteur, qui est obtenue à partir d'une propriété (FactorValue) dans un contrôle personnalisé (MyControl).

Le convertisseur:

public class MyConverter : DependencyObject, IValueConverter 
{ 
    // The property used as a parameter 
    public double Factor 
    { 
     get { return (double) GetValue(FactorProperty); } 
     set { SetValue(FactorProperty, value); } 
    } 

    // The dependency property to allow the property to be used from XAML. 
    public static readonly DependencyProperty FactorProperty = 
     DependencyProperty.Register(
     "Factor", 
     typeof(double), 
     typeof(MyConverter), 
     new PropertyMetadata(1.15d)); 

    #region IValueConverter Members 

    object IValueConverter.Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     // Use the property in the Convert method instead of "parameter" 
     return (double) value * Factor; 
    } 

    object IValueConverter.ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 

    #endregion 
} 

Utilisation en XAML:

<MyConverter x:Key="MyConv" 
      Factor={Binding ElementName=MyControl, Path=FactorValue} 
/> 

Ainsi, vous pouvez maintenant déclarer une propriété de dépendance pour chaque paramètre dont vous avez besoin dans votre convertisseur et le lier.