Пароль PasswordFox для WPF - "{DependencyProperty.UnsetValue}"

Я делаю программу чата.

Я разработал список чатов с использованием 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 ответа

Решение

Из соображений безопасности невозможно привязать напрямую к PasswordProperty.

Посмотрите здесь!

Используя 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}"/>
Другие вопросы по тегам