티스토리 툴바


Data Virtualization

WPF & Silverlight 2012/01/30 12:58 Posted by 꼬몽
http://bea.stollnitz.com/files/52/DataVirtualization.pdf
저작자 표시

PasswordBox DataBinding

WPF & Silverlight 2011/04/06 19:41 Posted by 꼬몽

PasswordBox는 보안 때문인지 Data Binding이 되지 않습니다.
별도의 첨부 속성(Attached Property)을 갖는 도움 클래스 만들고 이를 이용하면 Data Binding이 가능합니다.
이를 이용한 XAML 코드는 아래와 같습니다.

<PasswordBox xamlHelpers:PasswordBoxAssistant.BindPassword="True" xamlHelpers:PasswordBoxAssistant.BoundPassword="{Binding Path=Password}" />

아래는 PasswordBoxAssistant의 구현부분 입니다.

public static class PasswordBoxAssistant
{
   public static readonly DependencyProperty BoundPassword =
        DependencyProperty.RegisterAttached("BoundPassword", typeof(string), typeof(PasswordBoxAssistant), new FrameworkPropertyMetadata(string.Empty, OnBoundPasswordChanged));

    public static readonly DependencyProperty BindPassword = DependencyProperty.RegisterAttached(
        "BindPassword", typeof(bool), typeof(PasswordBoxAssistant), new PropertyMetadata(false, OnBindPasswordChanged));

    private static readonly DependencyProperty UpdatingPassword =
        DependencyProperty.RegisterAttached("UpdatingPassword", typeof(bool), typeof(PasswordBoxAssistant));

    private static void OnBoundPasswordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        PasswordBox box = d as PasswordBox;

        if (d == null || !GetBindPassword(d))
        {
            return;
        }

        box.PasswordChanged -= HandlePasswordChanged;

        string newPassword = (string)e.NewValue;

        if (!GetUpdatingPassword(box))
        {
            box.Password = newPassword;
        }

        box.PasswordChanged += HandlePasswordChanged;
    }

    private static void OnBindPasswordChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
    {
        PasswordBox box = dp as PasswordBox;

        if (box == null)
        {
            return;
        }

        bool wasBound = (bool)(e.OldValue);
        bool needToBind = (bool)(e.NewValue);

        if (wasBound)
        {
            box.PasswordChanged -= HandlePasswordChanged;
        }

        if (needToBind)
        {
            box.PasswordChanged += HandlePasswordChanged;
        }
    }

    private static void HandlePasswordChanged(object sender, RoutedEventArgs e)
    {
        PasswordBox box = sender as PasswordBox;

        SetUpdatingPassword(box, true);
        SetBoundPassword(box, box.Password);
        SetUpdatingPassword(box, false);
    }

    public static void SetBindPassword(DependencyObject dp, bool value)
    {
        dp.SetValue(BindPassword, value);
    }

    public static bool GetBindPassword(DependencyObject dp)
    {
        return (bool)dp.GetValue(BindPassword);
    }

    public static string GetBoundPassword(DependencyObject dp)
    {
        return (string)dp.GetValue(BoundPassword);
    }

    public static void SetBoundPassword(DependencyObject dp, string value)
    {
        dp.SetValue(BoundPassword, value);
    }

    private static bool GetUpdatingPassword(DependencyObject dp)
    {
        return (bool)dp.GetValue(UpdatingPassword);
    }

    private static void SetUpdatingPassword(DependencyObject dp, bool value)
    {
        dp.SetValue(UpdatingPassword, value);
    }
}

자세한 내용은 아래 링크를 참고하시기 바랍니다.
http://www.tanguay.info/web/index.php?pg=codeExamples&id=220

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