2012-06-30 3 views
1

이것은 다른 코드가 아닌 일부 코드에서 작동하는 가장 이상한 것입니다. 다음 코드는 TextBox를 하위 클래스로 사용하는 클래스입니다 (참고 : 중요한지는 모르지만 개인 필드 _realText에서 설정/가져 오기 위해 Text 속성을 하위 클래스로 지정 함)TextBox.Text 속성을 설정하면 설정되지 않았습니까?

아래 코드에서 첫 번째 기준은 다음과 같습니다. 텍스트 = this.RealText는 정상적으로 작동합니다. 우리는 또한 MaskData() 메서드 내에서 그것을 설정하고 작동합니다! !!!! 그렇다면 세계에서 if (! field.isSecure) 섹션에서 작동하지 않는 이유는 무엇입니까? (무슨 뜻인지 로그를보세요). base.Text = temp 이후에 Invalidate(), Update()를 추가하려고 시도했지만 도움이되지 않았습니다.

코드 :

private void SetupTextInBox() 
    { 
     if (isInManualMode) 
     { 
      this.ReadOnly = false; 
      base.Text = this.RealText; 
     } 
     else 
     { 
      this.ReadOnly = true; 
      if (!field.IsSecure) 
      { 
       string temp = this.RealText; 
       log.Info("This field is not secure so show it. field=" + field.Variable + " real='" + temp+"'"); 
       base.Text = temp; 
       log.Info("text value='" + base.Text+"'"); 
       return; 
      } 
      else 
      { 
       MaskData(); 
      } 
     } 
    } 

로그

2012-06-30 07:15:51,468 [1] INFO AlpineAccess.Plugins.SecureTalkPlugin.SecureTextControl (null) - This field is not secure so show it. field=1.acc real='2222' 
2012-06-30 07:15:51,468 [1] INFO AlpineAccess.Plugins.SecureTalkPlugin.SecureTextControl (null) - text value='' 

편집 :이 방법은 항상 동일한 스레드에서 호출합니다. 그것은 다른 곳에서 눌려진 전화기의 신호음을 알려주는 서버 알림에서 왔으며, 그 스레드는 BeginInvoke를 호출하여 GUI/컨트롤 스레드 또는 기타 등등에 넣습니다. 위의 방법에서 상류

코드는

public void AppendDTMFDigit(string digit) 
    { 
     log.Info("specified="+field.MaxSpecified+" someone appending dtmf digit on field=" + field.Variable+" fieldMax="+field.Max+" len="+RealText.Length); 
     if (field.MaxSpecified && this.RealText.Length >= field.Max) 
      return; //shortcut out since we can't exceed max digits 

     BeginInvoke(new MethodInvoker(delegate() 
     { 
      this.RealText = this.RealText + digit; 
      log.Info("new realtext=" + this.RealText); 
      SetupTextInBox(); 
     } 
     )); 
    } 

더 많은 정보

: 나는 내 모든 클라이언트 코드를 변경하는 경우, 텍스트 속성을 사용을 중지하고 RealText 속성을 사용하고 Text 속성을 재정의 중지에 다음 작품 벌금. (당연히 지금은 컨트롤을 TextBox로 바꿀 수 없으며 RealText 속성을 참조하는 클라이언트 코드를 많이 변경하지 않고도 쉽게 되돌릴 수는 없지만 .... 그래도 그걸로 살아야 할 수도 있습니다. ... 이상한 버그의 일종처럼 보인다

MORE INFO :... 그것으로 스테핑 디버거를 가지고 이것은 매우 이상한

이 매우 이상한 것들 그것은 게터에 단계

  1. , setter가 아닌가?
  2. TextBox의 Text 속성 대신 MY Text 속성을 사용합니다.

grrrrr, 왜 그게 ... 주요 버그처럼 들릴까요? 내 말은, base.Text는 수퍼 클래스의베이스를 참조해야합니다. 맞습니까? - 당신이 주석 않는 딘 힐러가 지금 Text 속성이 여기에 텍스트 method 속성 코드를 작동하지 않습니다이 사용자 제어를위한

public override string Text 
    { 
     get 
     { 
      return RealText; 
     } 
     set 
     { 
      if (value == null) 
       throw new ArgumentException("Not allowed to set RealText to null. Set to empty string instead"); 
      RealText = value; 
     } 
    } 
+0

무엇 디버깅하게;의 일을 '임시'의 e 값? 이게 진짜 텍스트인가요? 그렇다면이 속성은 프라이빗 백킹 필드를 올바르게 읽는 것입니까? 후원 필드가 설정되어 있습니까? 코드를 밟았 니? – Charleh

+0

죄송합니다. 제 기록에는 실제 기록 대신 임시 기록이 있어야하지만 기록에서 첫 번째 기록 진술에서 '2222'라는 임시 값을 볼 수 있습니다. –

+0

디버깅을하셨습니까? 당신의 세터가 실행되고 있다고 확신합니다 - 당신이 그것에 브레이크 포인트를 붙일 수있는 기회? 설정기에 들어가기 만하면됩니다 (보통 이것은 자동 단계 설정으로 설정되어 있지만 디버거 설정에서 해제 할 수 있습니다). – Charleh

답변

1

전체 소스를 추가

편집 (당신은 RealText를 사용하는 것 속성을 추가하고 base.Text가 제대로 작동하지 않는 대신 클라이언트에 노출합니다.

RealText = Text; 

(당신이베이스를 지정하지 않았기 때문에)이 가장 파생 된 '텍스트'속성을 호출합니다 : 당신이 당신의 라인 중 하나에 본이 - 당신이 텍스트를 무시했습니다 확인

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Drawing; 
using System.Data; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using log4net; 
using IntraNext.Win32.Config; 

namespace AlpineAccess.Plugins.SecureTalkPlugin 
{ 

    public partial class SecureTextBox : TextBox 
    { 
     private static readonly ILog log = LogManager.GetLogger(typeof(SecureTextControl)); 

     private static readonly Color COLOR_FOCUSED = Color.Yellow; 
     private static readonly Color COLOR_FOCUSED_MANUALMODE = Color.PaleGreen; 

     private FocusEvent focusListener; 
     private Field field; 
     private bool isInManualMode; 
     private EventHandler textChanged; 
     private string RealText; 

     public SecureTextBox() 
     { 
      InitializeComponent(); 
      RealText = ""; 
     } 

     internal void Initialize(Field field, FocusEvent focusList, EventHandler textChanged) 
     { 
      this.focusListener = focusList; 
      this.textChanged = textChanged; 
      this.field = field; 

      this.Enter += new EventHandler(SecureTextBox_Enter); 
      this.Leave += new EventHandler(SecureTextBox_Leave); 
      this.TextChanged += new EventHandler(SecureTextBox_TextChanged); 

      MenuItem mnuItemNew = new MenuItem(); 
      mnuItemNew.Text = "&Clear"; 

      //THIS textbox HAS a context menu ALREADY BUT here we assign a new context menu to 
      //our text box to replace the old one which had cut, paste etc. that we don't want 
      //the agent using... 
      this.ContextMenu = new ContextMenu(); 
      this.ContextMenu.MenuItems.Add(mnuItemNew); 

      mnuItemNew.Click += new EventHandler(clear_Click); 

      SwitchModes(); 
     } 

     void SecureTextBox_TextChanged(object sender, EventArgs e) 
     { 
      if(isInManualMode) //make sure if in manual mode, we keep changes up to date in realText field 
       RealText = Text; 
      textChanged(sender, e); 
     } 

     void clear_Click(object sender, EventArgs e) 
     { 
      ClearAll(); 
     } 

     internal void SetManualMode(bool inManual) 
     { 
      if (isInManualMode == inManual) 
       return; //we don't care if there is no change so return; 

      isInManualMode = inManual; 
      SwitchModes(); 
     } 

     void SecureTextBox_Leave(object sender, EventArgs e) 
     { 
      log.Info("exiting=" + field.Variable); 
      focusListener(field.Variable, false, this.RealText); 
      BeginInvoke(new MethodInvoker(delegate() 
      { 
       ChangeBackground(); 
      } 
      ));    
     } 

     void SecureTextBox_Enter(object sender, EventArgs e) 
     { 
      log.Info("entering=" + field.Variable); 
      focusListener(field.Variable, true, this.RealText); 
      BeginInvoke(new MethodInvoker(delegate() 
      { 
       ChangeBackground(); 
      } 
      )); 
     } 

     private void SwitchModes() 
     { 
      SetupTextInBox(); 
      ChangeBackground(); 
     } 

     private void SetupTextInBox() 
     { 
      if (isInManualMode) 
      { 
       this.ReadOnly = false; 
       base.Text = RealText; 
      } 
      else if (!field.IsSecure) 
      { 
       this.ReadOnly = true; 
       string temp = RealText; 
       base.Text = temp; 
       Invalidate(); 
       log.Info("txt=" + base.Text + " temp=" + temp); 
      } 
      else //not manual mode and IsSecure so mask it and make it readonly 
      { 
       this.ReadOnly = true; 
       MaskData(); 
      } 
     } 

     private void MaskData() 
     { 
      log.Debug("mask=" + this.field.NumBeginDigitsToMaskSpecified + " num=" + field.NumBeginDigitsToMask + " txtLen=" + RealText.Length); 
      int numDigitsToMask = RealText.Length; 
      if (this.field.NumBeginDigitsToMaskSpecified && this.field.NumBeginDigitsToMask < RealText.Length) 
      { 
       int numDigits = this.field.NumBeginDigitsToMask; 
       string maskedPart = "".PadLeft(numDigits, '●'); 
       string unmasked = RealText.Substring(numDigits); 
       string full = maskedPart + unmasked; 
       base.Text = full; 
      } 
      else 
      { 
       log.Debug("masking all digits"); 
       base.Text = "".PadLeft(RealText.Length, '●'); 
      } 
     } 

     private void ChangeBackground() 
     { 
      if (isInManualMode) 
       SetManualModeColor(); 
      else 
       SetNonManualModeColor(); 
     } 

     private void SetNonManualModeColor() 
     { 
      if (this.Focused) 
       this.BackColor = COLOR_FOCUSED; 
      else 
       this.BackColor = Control.DefaultBackColor; 
     } 

     private void SetManualModeColor() 
     { 
      if (this.Focused) 
       this.BackColor = COLOR_FOCUSED_MANUALMODE; 
      else 
       this.BackColor = Control.DefaultBackColor; 
     } 

     public void AppendDTMFDigit(string digit) 
     { 
      log.Info("manualmode="+isInManualMode+" specified=" + field.MaxSpecified + " someone appending dtmf digit on field=" + field.Variable + " fieldMax=" + field.Max + " len=" + RealText.Length); 

      if (isInManualMode) 
       return; 
      else if (field.MaxSpecified && RealText.Length >= field.Max) 
       return; //shortcut out since we can't exceed max digits 

      BeginInvoke(new MethodInvoker(delegate() 
      { 
       RealText = RealText + digit; 
       SetupTextInBox(); 
      } 
      )); 
     } 

     internal void ClearAll() 
     { 
      log.Info("Cleared textbox for =" + field.Variable); 
      base.Text = ""; 
      RealText = ""; 
      SetError(""); 
     } 

     public override string Text 
     { 
      get 
      { 
       return RealText; 
      } 
      set 
      { 
       if (value == null) 
        throw new ArgumentException("Not allowed to set RealText to null. Set to empty string instead"); 
       RealText = value; 
      } 
     } 

     /** 
     * Set to "" to clear the error or set anything to make valid 
     */ 
     public void SetError(string error) 
     { 
      if (!this.IsHandleCreated) 
       return; 

      SecureTextBox box = this; 
      //set to "" to clear the error 
      BeginInvoke(new MethodInvoker(delegate() 
      { 
       errorProvider1.SetError(box, error); 
      })); 
     } 
    } 
} 
+0

그것은 할당하고있는 다른 속성의 값을 얻고 있기 때문에 Getter에 들어갈 것입니다. 또한 Textbox.Text에 대한 소스가 없으므로 아마도 setter로 들어 가지 않습니다. 또한 약간의 혼란은 필드와 동일한 속성 이름을 지정하는 것입니다. 일반적으로 private 필드는 접두어를 사용하여 코드에서 구분할 수 있습니다 (예 : RealText 대신 RealText). - 모양이 바뀌 었습니다. – Charleh

+0

어, 임시는 "local "변수는 그렇게 이해가되지 않습니다. 그것은 위의 코드에서 base.Text = temp의 Text 속성 getter로 넘어 간다. –

+0

내 대답을 확인 했습니까? (프로젝트 디버깅이 어렵지 않고) 내 대답을 확인 했습니까? 아직 재정의 된 텍스트 문제가 있습니다. – Charleh

1

당신은 그 자체

예에 RealText를 설정하는 의미 전류 제어

에 오버라이드 (override) '텍스트'를 호출합니다 조금있다

void SecureTextBox_TextChanged(object sender, EventArgs e) 
{ 
    if (isInManualMode) //make sure if in manual mode, we keep changes up to date in realText field 
    RealText = Text; <---- **THIS CALLS THE OVERIDDEN 'Text' BELOW** 

    ... snip 

전화

public override string Text 
{ 
    get { return RealText; } 
} 

... 너트!

은 당신이해야 할 의미입니까?

void SecureTextBox_TextChanged(object sender, EventArgs e) 
{ 
    if (isInManualMode) //make sure if in manual mode, we keep changes up to date in realText field 
    RealText = base.Text; <--- THIS? 

신중하게, 나는 이것이 당신의 문제

또한

조금 ... 예를 들어, 당신의 이름 지정 규칙을 변경하는 것이 유용 할 수 있습니다 중 하나입니다 내기 코드를 확인 나는/개인 보호 분야

대신
private string RealText; 

은 일반적으로 보통 속성을 사용하여, 공공 필드를 노출시키지 마십시오하지만 그렇게되면 내가하는 경향이 속성

위한 캡의
private string _realText; 

에 밑줄을 사용하는 경향이 내가 속성

을 위해 할 것과 같은 케이스를 사용 이것은이 코드에서 속성과 필드를 구분하기 쉽게 있도록하고 약간에게 쉽게

+0

좋은 캐치,하지만 수동 모드로 테스트를 실행할 때 아니에요. 나는 보안 모드에서 그 라인을 치지 않는다. (비록 내가 고칠 것이다.) 드디어 대신 RealText를 노출하고 Text 속성 재정의를 주석 처리하고 다른 변경 사항없이 작업했습니다. –

+0

당신이 그것을 다행으로 보았을 때, 때때로 이런 종류의 실수가 시간을 먹을 수 있습니다! – Charleh

관련 문제