2009-03-03 3 views
0

내 데이터 개체에 바인딩 된 텍스트 상자가 있습니다. 유효성 검사가 실패하면 오류 메시지가 포함 된 팝업을 표시하고 싶습니다. XAML에서는 제대로 작동합니다. 나는 다음과 같은 XAML을 사용하고 있습니다 :코드에서 Popup.IsOpen에 바인딩하는 방법 Validation.HasError 코드에서

<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> 

내 문제는 내가 팝업 및 코드에서 바인딩을 생성하고 난 그것을 작동시킬 수 없다는 것입니다. 여러 가지 옵션을 시도했습니다. 나는 또한 바인드가 전혀 작동하는지 확인하기 위해 더미 변환기를 사용했다. 그것은 바인딩 (그것은 초기 값을 얻을) 만들 때 작동하지만 그 후에 아무것도 일어나지 않는 것 같습니다. Validation.HasError가 올바르게 업데이트되는지 (TextBox의 테두리가 빨간색으로 변함) 볼 수 있지만 그게 전부입니다. 내 더미 변환기가 호출되지 않습니다. 다음은 내가 사용하고있는 코드입니다 :

Popup popup = new Popup(); 
    popup.Name = "somepopup"; 
    // Source is the textbox which is bound to the data object 
    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)"); 
    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); 

답변

3

그냥 간단한 테스트를했는데 정상적으로 작동했습니다. 코드 숨김 여기

<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> 

된다 : 여기 내 XAML입니다

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

는 또한 간단한 해결책을 만들어 코드에서 복사가 잘 달렸다. Kent는 XAML에서 자신의 Popup을 선언했지만 Popup을 만들고 바인딩을 설정하기 위해 정확한 코드를 사용 했으므로 그 차이가 문제의 원인이되어서는 안됩니다.

소스 변수의 출처를 게시 할 수 있는지 궁금합니다. 당신은 그것을 보여주지 않으며 그것이 당신이 생각하는 것이라면 궁금합니다.

또 다른 시도는 가비지 수집중인 팝업에 대한 참조를 유지하는 것입니다. 바인딩을 사용하면 주간 이벤트 처리기가 변경 알림을 사용하므로 Popup 인스턴스에 대한 지속적인 링크가 아닐 수 있습니다. 나는 그러나 이것이있을 법하지 않다고 생각하지만, 한 발의 가치가 있을지도 모릅니다.

참고로이 테스트에 사용 된 코드는 다음과 같습니다.

XAML 파일 :

<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> 

코드 숨김.

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; 
      } 
     } 
    } 
관련 문제