2010-10-13 5 views
1

Je souhaite définir BorderThickness d'une bordure d'un UserControl à l'aide de 4 TextBoxes, mais je n'arrive pas à le faire fonctionner.WPF: Liaison TwoWay entre 4 TextBoxes et 1 Border.Margin

code XAML montrant le problème (seul ce code en combinaison avec le convertisseur est nécessaire):

<Window 
    x:Class="BorderThicknessBindingTest.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:BorderThicknessBindingTest="clr-namespace:BorderThicknessBindingTest" 
    Height="300" Width="500"> 
    <Window.Resources> 
     <BorderThicknessBindingTest:ThicknessConverter x:Key="ThicknessConverter"/> 
    </Window.Resources> 

    <Grid Margin="10"> 
     <Border 
      x:Name="MyBorder" 
      BorderBrush="Black" 
      Background="AliceBlue" 
      BorderThickness="3"/> 
     <TextBox 
      HorizontalAlignment="Center" VerticalAlignment="Center" 
      Text="{Binding Path=BorderThickness.Left, ElementName=MyBorder, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource ThicknessConverter}}"/> 
    </Grid> 
</Window> 

Un convertisseur est nécessaire pour analyser la chaîne d'entrée dans la zone de texte:

public class ThicknessConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return value; // don't need to do anything here 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     double d; 
     Double.TryParse((string) value, out d); // Thickness.Left doesn't take a string 
     return d; 
    } 
} 

Le TextBox affiche correctement la partie gauche de l'épaisseur, mais l'édition de la zone de texte n'entraîne pas de changement dans la façon dont le côté gauche de la bordure est rendu. Bizarrement, la valeur que j'ai définie dans le TextBox pour Thickness.Left persiste, donc il semble que la valeur soit définie, mais le rendu n'est pas mis à jour. Dans l'exemple de code, la modification de la valeur dans la zone de texte, puis le redimensionnement de la fenêtre, montre que la bordure sur la gauche prend de l'espace supplémentaire, mais cet espace est vide.

Est-ce que quelqu'un sait comment résoudre ce problème?

Répondre

2

Ce n'est pas mise à jour de façon dynamique l'élément à l'écran parce que rien ne l'a dit l'élément qu'un champ dans sa propriété BorderThickness a changé. Vous devez notifier l'élément que son BorderThickness a changé, ce que vous ne pouvez faire qu'en définissant directement la propriété de dépendance à une nouvelle valeur - disons, en en faisant la cible d'une liaison à un objet qui modifie la notification.

C'est un peu pénible de faire un modèle de vue pour cela, mais une fois que c'est fait, c'est fait.

La fenêtre:

<Window x:Class="ThicknessDemo.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ComponentModel="clr-namespace:System.ComponentModel;assembly=System" xmlns:ThicknessDemo="clr-namespace:ThicknessDemo" Title="MainWindow" Height="350" Width="525"> 
    <Window.Resources> 
     <ThicknessDemo:ThicknessViewModel x:Key="thickness" /> 
    </Window.Resources> 
     <DockPanel DataContext="{StaticResource thickness}"> 
      <Border DockPanel.Dock="Top" 
        Width="100" 
        Height="50" 
        Margin="5" 
        BorderBrush="Blue" 
        BorderThickness="{Binding Thickness}" /> 
      <TextBox DockPanel.Dock="Top" 
         Text="{Binding Left, Mode=TwoWay}" /> 
      <TextBox DockPanel.Dock="Top" 
         Text="{Binding Right, Mode=TwoWay}" /> 
      <TextBox DockPanel.Dock="Top" 
         Text="{Binding Top, Mode=TwoWay}" /> 
      <TextBox DockPanel.Dock="Top" 
         Text="{Binding Bottom, Mode=TwoWay}" /> 
      <TextBlock DockPanel.Dock="Top" /> 
     </DockPanel> 
</Window> 

Le modèle de vue:

public class ThicknessViewModel : INotifyPropertyChanged 
{ 
    private void OnPropertyChanged(string propertyName) 
    { 
     PropertyChangedEventHandler h = PropertyChanged; 
     if (h != null) 
     { 
      h(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    public ThicknessViewModel() 
    { 
     _Thickness = new Thickness(1, 1, 1, 1); 
    } 

    private Thickness _Thickness; 

    public Thickness Thickness { get { return _Thickness; } set { _Thickness = value;} } 

    public double Left 
    { 
     get { return _Thickness.Left; } 
     set 
     { 
      _Thickness.Left = value; 
      OnPropertyChanged("Thickness"); 
     } 
    } 

    public double Right 
    { 
     get { return _Thickness.Right; } 
     set 
     { 
      _Thickness.Right = value; 
      OnPropertyChanged("Thickness"); 
     } 
    } 

    public double Top 
    { 
     get { return _Thickness.Top; } 
     set 
     { 
      _Thickness.Top = value; 
      OnPropertyChanged("Thickness"); 
     } 
    } 

    public double Bottom 
    { 
     get { return _Thickness.Bottom; } 
     set 
     { 
      _Thickness.Bottom = value; 
      OnPropertyChanged("Thickness"); 
     } 
    } 
} 
0

La me solution la plus simple se révèle être de simplement écouter l'événement TextChanged de la zone de texte et remplacez le BorderThickness en code derrière.

MainWindow.xaml:

<Window 
    x:Class="BorderThicknessBindingTest.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:BorderThicknessBindingTest="clr-namespace:BorderThicknessBindingTest" 
    Height="300" Width="500"> 

    <Grid Margin="10"> 
     <Border 
      x:Name="MyBorder" 
      BorderBrush="Black" 
      Background="AliceBlue" 
      BorderThickness="3"/> 
     <TextBox 
      x:Name="MyTextBox" 
      HorizontalAlignment="Center" VerticalAlignment="Center" 
      Text="{Binding Path=BorderThickness.Left, ElementName=MyBorder, Mode=OneWay}"/> 
    </Grid> 
</Window> 

MainWindow.xaml.cs, dans le constructeur:

MyTextBox.TextChanged += (sender, e) => 
{ 
    double d; 
    if (!double.TryParse(MyTextBox.Text, out d)) return; 
    var t = MyBorder.BorderThickness; 
    t.Left = d; 
    MyBorder.BorderThickness = t; 
}; 

En ce moment, cela fonctionne pour moi, la solution de Robert Rossney est mieux.

Questions connexes