2009-03-03 11 views
0

binden Ich habe eine Textbox, die an mein Datenobjekt gebunden ist. Wenn die Validierung fehlschlägt, möchte ich ein Popup anzeigen, das die Fehlermeldung enthält. In XAML funktioniert das gut. Ich verwende den folgenden XAML:Wie an Popup.IsOpen zu Validation.HasError in Code

<TextBox Height="23" Margin="54,12,104,0" Name="textBox1" 
VerticalAlignment="Top" Text="{Binding Value, ValidatesOnExceptions=True, UpdateSourceTrigger=PropertyChanged}"></TextBox> 

     <Popup Name="myPopup" PlacementTarget="{Binding ElementName=textBox1}" 
         IsOpen="{Binding ElementName=textBox1, Path=(Validation.HasError), Mode=OneWay}" 
         > 
      <TextBlock Name="myPopupText" Background="LightBlue" Foreground="Blue"> 
         The value is invalid 
      </TextBlock> 
     </Popup> 

Mein Problem ist, dass ich das Popup und Bindung in Code erstellen, und ich kann es nicht zu arbeiten. Ich habe verschiedene Möglichkeiten ausprobiert. Ich habe auch Dummy-Konverter verwendet, nur um zu sehen, ob die Bindung überhaupt funktioniert. Es scheint, dass die Bindung funktioniert, wenn ich sie erstelle (sie erhält den Anfangswert), aber danach passiert nichts. Ich kann sehen, dass die Validation.HasError korrekt aktualisiert (TextBox-Rahmen wird rot), aber das ist es. Mein Dummy-Konverter wird nicht aufgerufen. Folgendes ist der Code, den ich benutze:

Antwort

3

Habe einfach einen einfachen Test und es hat gut funktioniert. Hier ist meine XAML:

<Window x:Name="_root" x:Class="WpfApplication1.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="300" Width="300"> 
    <StackPanel> 
     <TextBox x:Name="_textBox"> 
      <TextBox.Text> 
       <Binding Path="Text" ElementName="_root" UpdateSourceTrigger="PropertyChanged"> 
        <Binding.ValidationRules> 
         <ExceptionValidationRule/> 
        </Binding.ValidationRules> 
       </Binding> 
      </TextBox.Text> 
     </TextBox> 
     <!--<Popup x:Name="_popup" IsOpen="{Binding (Validation.HasError), ElementName=_textBox, Mode=OneWay}">--> 
     <Popup x:Name="_popup"> 
      <Border BorderThickness="1" BorderBrush="Black" Background="White"> 
       <TextBlock>Here I am.</TextBlock> 
      </Border> 
     </Popup> 
    </StackPanel> 
</Window> 

Und hier ist der Code-behind:

using System; 
using System.Windows; 
using System.Windows.Controls.Primitives; 
using System.Windows.Data; 

namespace WpfApplication1 
{ 
    public partial class Window1 : Window 
    { 
     public string Text 
     { 
      get { return "Text"; } 
      set { if (value != "Text") throw new InvalidOperationException("Bla"); } 
     } 

     public Window1() 
     { 
      InitializeComponent(); 

      var binding = new Binding("(Validation.HasError)"); 
      binding.Source = _textBox; 
      binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged; 
      binding.Mode = BindingMode.OneWay; 
      binding.NotifyOnValidationError = true; 
      binding.ValidatesOnExceptions = true; 
      //binding.Converter = new TempValueConverter(); 
      _popup.SetBinding(Popup.IsOpenProperty, binding); 
     } 

     private sealed class TempValueConverter : IValueConverter 
     { 
      #region IValueConverter Members 

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

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

      #endregion 
     } 
    } 
} 
0

Ich habe auch eine einfache Lösung und in Ihrem Code kopiert und es lief ganz gut. Kent hat sein Popup in XAML deklariert, aber ich habe Ihren genauen Code benutzt, um das Popup zu erstellen und die Bindung zu setzen, so dass dieser Unterschied nicht die Ursache des Problems für Sie sein sollte.

Ich frage mich, ob Sie posten könnten, wo Ihre Quellvariable herkommt. Du zeigst das nicht und ich frage mich, ob es das ist, was du denkst.

Eine andere Sache, die Sie vielleicht versuchen könnten, ist, einen Verweis auf das Popup zu halten, wenn es Müll gesammelt wird. Ich glaube, dies könnte möglich sein, als ob ich mich richtig erinnere, dass die Bindung einen Wochen-Event-Handler für die Änderungsbenachrichtigung verwendet, so dass sie keine dauerhafte Verbindung zur Popup-Instanz darstellen würde. Ich denke, das ist unwahrscheinlich, aber vielleicht einen Versuch wert.

FYI der Code, den ich verwendet habe, um dies zu testen, ist wie folgt.

XAML-Datei:

<Window x:Class="PopupOpenBindingTest.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" 
    Height="300" 
    Width="300"> 
<Grid> 
    <TextBox Height="23" 
      Margin="54,12,104,0" 
      Name="textBox1" 
      VerticalAlignment="Top" 
      Text="{Binding Text, ValidatesOnExceptions=True, UpdateSourceTrigger=PropertyChanged}" /> 
</Grid></Window> 

-Code-behind.

public partial class Window1 : Window 
{ 
    public Window1() 
    { 
     InitializeComponent(); 

     DataContext = new DataObjectTest(); 
     this.Loaded += new RoutedEventHandler(Window1_Loaded); 
    } 

    void Window1_Loaded(object sender, RoutedEventArgs e) 
    { 
     TextBox source = textBox1; 

     Popup popup = new Popup(); 
     popup.Name = "somepopup"; 
     popup.PlacementTarget = source; 
     popup.Placement = PlacementMode.Bottom; 
     TextBlock txtblock = new TextBlock(); 
     txtblock.Background = Brushes.LightBlue; 
     txtblock.Foreground = Brushes.Blue; 
     txtblock.Text = "this is the error message"; 
     popup.Child = txtblock; 
     Binding is_open_binding = new Binding("(Validation.HasError)");// { Path = new PropertyPath(Validation.HasErrorProperty) }; 
     is_open_binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged; 
     is_open_binding.Source = source; 
     is_open_binding.Mode = BindingMode.OneWay; 
     is_open_binding.NotifyOnValidationError = true; 
     is_open_binding.ValidatesOnExceptions = true; 
     //is_open_binding.Converter = new TempValueConverter(); 
     popup.SetBinding(Popup.IsOpenProperty, is_open_binding); 
    } 

    public class DataObjectTest 
    { 
     private string _text = string.Empty; 

     public string Text 
     { 
      get { return _text; } 
      set 
      { 
       if (value.Length > 5) 
        throw new InvalidOperationException("Blah blah blah"); 

       _text = value; 
      } 
     } 
    } 
Verwandte Themen