Decimal TextBox 로직 구현

C# 2016. 9. 12. 17:49 Posted by 꼬몽

원리는 TextBox를 편집을 하더라도 소수점이나 정수의 끝에서의 위치는 변함이 없는 것에 착안하여 구연한 로직입니다.

WinForm으로 만든 로직이지만 이 것을 참고하면 다른 곳에서도 구연에 문제가 없을 것입니다.


protected override void OnTextChanged(EventArgs e)
{
    if (isInTextChanged)
        return;
    isInTextChanged = true;

    string text = Text;
    if (0 < text.Length && ',' == text[0])
        text = text.Substring(1);

    Decimal dec;
    if (Decimal.TryParse(text, out dec))
    {
        if (0 == dec)
        {
            Text = 0.ToString("N" + _precision);
            SelectionStart = 1;
        }
        else
        {
            var lenOrg = text.Length;
            var posPointOrg = text.LastIndexOf('.');
            if (posPointOrg < 0)
                posPointOrg = lenOrg;
            var offsetCaret = posPointOrg - SelectionStart;
            if (0 < offsetCaret && 3 == offsetCaret % 4) // 콤마의 위치이면 한칸 앞으로
                offsetCaret++;

            text = dec.ToString("N" + _precision);
            var lenDest = text.Length;
            var posRevPointDest = 0 < _precision ? _precision + 1 : 0; // 0이 아닌 경우 소수점 추가
            var posPointDest = lenDest - posRevPointDest;

            Text = text;
            var pos = posPointDest - offsetCaret;
            if (pos < 0)
                pos = 0;
            SelectionStart = pos;
        }
    }

    isInTextChanged = false;
}

private bool isInTextChanged;


댓글을 달아 주세요

PasswordBox DataBind하는 방법

WPF & Silverlight 2016. 9. 12. 17:37 Posted by 꼬몽

WPF의 PasswordBox 컨트롤은 보안적인 이유로 TextBox처럼 DataBind가 되지 않습니다.

DataBind를 하기 위해서는 String 대신 SecureString Type으로 Behavior를 이용을 하면 됩니다.


코드는 아래와 같습니다.

public class PasswordBoxBehavior : Behavior<PasswordBox>
{
    // BoundPassword
    public SecureString BoundPassword
    {
        get { return (SecureString)GetValue(BoundPasswordProperty); }
        set { SetValue(BoundPasswordProperty, value); }
    }
    public static readonly DependencyProperty BoundPasswordProperty = DependencyProperty.Register("BoundPassword",
        typeof(SecureString), typeof(PasswordBoxBehavior), new FrameworkPropertyMetadata(OnBoundPasswordChanged));
    protected override void OnAttached()
    {
        this.AssociatedObject.PasswordChanged += AssociatedObjectOnPasswordChanged;
        base.OnAttached();
    }
    /// <summary>
    /// Link up the intermediate SecureString (BoundPassword) to the UI instance
    /// </summary>
    private void AssociatedObjectOnPasswordChanged(object s, RoutedEventArgs e)
    {
        this.BoundPassword = this.AssociatedObject.SecurePassword;
    }
    /// <summary>
    /// Reacts to password reset on viewmodel (ViewModel.Password = new SecureString())
    /// </summary>
    private static void OnBoundPasswordChanged(object s, DependencyPropertyChangedEventArgs e)
    {
        var box = ((PasswordBoxBehavior)s).AssociatedObject;
        if (box != null)
        {
            if (((SecureString)e.NewValue).Length == 0)
                box.Password = string.Empty;
        }
    }
}

사용방법은 아래와 같습니다.
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
- - - -
<PasswordBox VerticalAlignment="Top">
    <i:Interaction.Behaviors>
        <cb:PasswordBoxBehavior BoundPassword="{Binding Password, Mode=OneWayToSource}" />
    </i:Interaction.Behaviors>
</PasswordBox>


그런데 Binding 되는 Password는 string이 아닌 SecureString이므로 직접 읽을 수 없으로 아래의 방법으로 읽으면 됩니다.

IntPtr pStr = Marshal.SecureStringToCoTaskMemUnicode(Password);
Debug.WriteLine(Marshal.PtrToStringUni(pStr));
Marshal.ZeroFreeCoTaskMemUnicode(pStr);




댓글을 달아 주세요

Silverlight나 WP에서는 WPF에 Data Binding시 UpdateSourceTrigger에 PropertyChanged로 할 수 없기 때문에 TextBox에 값이 입력될 때마다 바인딩 된 Source로 반영할 수 없다.
이를 xaml에서도 할 수 있도록 하는 샘플

http://stackoverflow.com/questions/4833100/updatesourcetrigger-propertychanged-equivalent-for-a-windows-phone-7-textbox

댓글을 달아 주세요

Data Virtualization

WPF & Silverlight 2012. 1. 30. 12:58 Posted by 꼬몽
http://bea.stollnitz.com/files/52/DataVirtualization.pdf

댓글을 달아 주세요

Reactive Extension 예제

스크랩 2011. 9. 23. 22:32 Posted by 꼬몽
http://debop.egloos.com/3570951
http://rxwiki.wikidot.com/101samples 

댓글을 달아 주세요

.Net 비동기 스트림 처리

스크랩 2011. 7. 22. 09:24 Posted by 꼬몽
http://msdn.microsoft.com/ko-kr/magazine/cc337900.aspx

댓글을 달아 주세요

101 LINQ Samples

스크랩 2011. 3. 30. 18:09 Posted by 꼬몽
http://blog.daum.net/gksdy2000/8006525

댓글을 달아 주세요

마우스 두개로 멀티터치

스크랩 2011. 3. 30. 08:55 Posted by 꼬몽

http://lunanesslab.tistory.com/143

댓글을 달아 주세요

C# Dispose Pattern

C# 2011. 3. 30. 01:08 Posted by 꼬몽

using System;
using System.ComponentModel;

// 기반 클래스의 구현
public class BaseClass : IDisposable
{
    // C# 소멸자. Finalize 메서드임
    ~BaseClass()
    {
        // 단순히 Dispose(false).
        Dispose(false);
    }

    public void Dispose()
    {
        Dispose(true);
    }

 
    // disposing 플래그를 통해 Finalize에서 managed 리소스
    // 를 정리하지 않도록(해당 리소스는 GC가 정리할 것임)
    protected virtual void Dispose(bool disposing)
    {
        // Dispose가 안불렸을 경우에만 정리작업
        if (!_disposed)
        {
            if (disposing)
            {
                // Managed 리소스 정리
                GC.SuppressFinalize(this); 
            }

            // Unmanaged 리소스 정리

            // Dispose가 불렸음을 설정
            _disposed = true;
        }
    }

    protected bool _disposed = false;
}

// 파생 클래스에서의 구현
public class Derived : BaseClass
{  
    protected override void Dispose(bool disposing)
    {
        // Dispose가 안불렸을 경우에만 정리작업
        if (!_disposed)
        {
            if (disposing)
            {
                // Managed 리소스 정리
            }

            // Unmanaged 리소스 정리

            // 부모 개체의 리소르를 정리
            base.Dispose(disposing);
        }


      if (disposing)
      {
         // managed 리소스의 정리
      }
      // Unmanaged 리소스 정리
      // 부모 개체의 리소스를 정리하도록
      base.Dispose(disposing);
   }
   // 파생 클래스에서는 소멸자 정의를 하지 않음(부모 소멸자
   // 에서 재정의된 Dispose를 호출할 것이므로)
}

댓글을 달아 주세요

TabControl안에 DataGrid로 화면을 구성한 경우 등에서 DataGrid가 Row를 추가하거나 Cell을 편집하는 중에 다른 탭을 누르고 다시 돌아오면 'AddNew 또는 EditItem 트랜잭션 중에는 'DeferRefresh'을(를) 사용할 수 없습니다.(DataGrid and 'DeferRefresh' is not allowed during an AddNew or EditItem transaction when quickly clicking)'라는 InvalidOperationException이 발생됩니다.
이것에 대해 구글링을 해보니 DataGrid를 공개한 CodeFlex WPF 홈에 가보니 해결 방법이 공개 되어 있습니다.
해결 방법은 적절한 이벤트들에 대해 IEditableCollectionView의 CancelNew와 CancelEdit를 호출하여 트랜잭션을 롤백하는 방법을 사용하면 됩니다.
이를 지원하기 위해서는 반드시 바인딩 객체에 IEditableObject가 구현되어야 합니다.
자세한 내용은 아래에서 확인하시기 바랍니다.
http://wpf.codeplex.com/workitem/10539

댓글을 달아 주세요