WPF PasswordBox密码是" {DependencyProperty.UnsetValue}"

时间:2014-09-10 08:08:28

标签: c# wpf binding passwordbox

我正在制作一个聊天程序。

我使用XAML设计了聊天室列表。

                                        <GridViewColumn x:Name="gridViewColumn_IsNeedPassword">
                                            <GridViewColumn.CellTemplate>
                                                <DataTemplate>
                                                    <PasswordBox x:Name="passwordBox_PW" MinWidth="100" IsEnabled="{Binding Path=IsNeedPassword}"/>
                                                </DataTemplate>
                                            </GridViewColumn.CellTemplate>
                                        </GridViewColumn>
                                        <GridViewColumn x:Name="gridViewColumn_EntryButton">
                                            <GridViewColumn.CellTemplate>
                                                <DataTemplate>
                                                    <Button Background="Aqua" Click="button_Entry_Click">
                                                        <StackPanel Orientation="Horizontal">
                                                            <Image Height="Auto" Width="Auto" Source="Resources/login.png"/>
                                                            <TextBlock Text="{Binding Converter={StaticResource EntryButtonConverter}}" VerticalAlignment="Center"/>
                                                        </StackPanel>
                                                        <Button.Tag>
                                                            <MultiBinding Converter="{StaticResource EntryButtonTagConverter}">
                                                                <Binding Path="ID"/>
                                                                <Binding Path="IsNeedPassword"/>
                                                                <Binding ElementName="passwordBox_PW" Path="Password"/>
                                                            </MultiBinding>
                                                        </Button.Tag>
                                                    </Button>
                                                </DataTemplate>
                                            </GridViewColumn.CellTemplate>
                                        </GridViewColumn>
                                        <GridViewColumn x:Name="gridViewColumn_DeleteButton">
                                            <GridViewColumn.CellTemplate>
                                                <DataTemplate>
                                                    <Button Background="Orange" Click="button_Delete_Click" IsEnabled="{Binding Path=Master, Converter={StaticResource DeleteButtonVisibilityConverter}}">
                                                        <StackPanel Orientation="Horizontal">
                                                            <Image Height="Auto" Width="Auto" Source="Resources/login.png"/>
                                                            <TextBlock Text="{Binding Converter={StaticResource DeleteButtonConverter}}" VerticalAlignment="Center"/>
                                                        </StackPanel>
                                                        <Button.Tag>
                                                            <Binding Path="ID"/>
                                                        </Button.Tag>
                                                    </Button>
                                                </DataTemplate>
                                            </GridViewColumn.CellTemplate>
                                        </GridViewColumn>
                                    </GridView.Columns>

像这样。

现在,在gridViewColumn_EntryButton我需要一些信息,例如RoomID + IsNeedPassword + PasswordText

所以我使用MultiBinding

EntryButtonTagConverter.Convert就是这样。

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        string[] result = Array.ConvertAll<object, string>(values, obj =>
        {
            return (obj == null) ? string.Empty : obj.ToString();
        });
        // RoomID + IsNeedPassword + PasswordText
        return result[0] + '\n' + result[1] + '\n' + result[2];
    }

当我调试时,result[2]PasswordText"{DependencyProperty.UnsetValue}"

但我输入了PasswordBox asdftest1234

我不知道为什么PasswordBox.Password财产无法访问。

任何一个想法?

感谢。

2 个答案:

答案 0 :(得分:1)

出于安全原因,无法直接绑定到PasswordProperty。

看看here!

答案 1 :(得分:0)

使用PasswordBoxAssistant可以绑定密码。

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

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

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

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

        // only handle this event when the property is attached to a PasswordBox  
        // and when the BindPassword attached property has been set to true  
        var ignoreBindProperty = false;
        if (box != null && box.Parent != null)
        {// TODO: Bind property change not set in case of hosting password box under Telerik datafield. That why I am ignoring the bind propery here - Morshed
            ignoreBindProperty = (box.Parent is Telerik.Windows.Controls.DataFormDataField);
        }

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

        // avoid recursive updating by ignoring the box's changed event  
        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)
    {
        // when the BindPassword attached property is set on a PasswordBox,  
        // start listening to its PasswordChanged event  

        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;

        // set a flag to indicate that we're updating the password  
        SetUpdatingPassword(box, true);
        // push the new password into the BoundPassword property  
        SetBoundPassword(box, box.Password);
        SetUpdatingPassword(box, false);
    }

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

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

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

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

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

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

并更改xaml

<PasswordBox helpers:PasswordBoxAssistant.BindPassword="true"
              helpers:PasswordBoxAssistant.BoundPassword="{Binding Path=Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=true}"/>