开发者

WP7 Custom Control Binding Inner Control

I'm creating a custom control that has a PasswordBox in it. How do I hook up a DependencyProperty of my custom control to the Password property of the PasswordBox?

From all the examples I see, hooking it up the password in the template using TemplateBinding shoul开发者_如何转开发d do the trick, but this doesn't seem to be working. What am I missing?

generic.xaml

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:CustomControlBinding="clr-namespace:CustomControlBinding">

    <Style TargetType="CustomControlBinding:PasswordBoxTest">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="CustomControlBinding:PasswordBoxTest">
                    <Grid Background="Transparent">
                        <PasswordBox Password="{TemplateBinding Text}" />
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</ResourceDictionary>

PasswordBoxTest.cs

namespace CustomControlBinding
{
    public class PasswordBoxTest : Control
    {
        public static readonly DependencyProperty TextProperty = DependencyProperty.Register( "Text", typeof( string ), typeof( PasswordBoxTest ), new PropertyMetadata( OnTextPropertyChanged ) );

        public string Text
        {
            get { return GetValue( TextProperty ) as string; }
            set { SetValue( TextProperty, value ); }
        }

        public PasswordBoxTest()
        {
            DefaultStyleKey = typeof( PasswordBoxTest );
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
        }

        private static void OnTextPropertyChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e )
        {
        }
    }
}


You have to use RelativeSource bindings, for it to work. Or you have to set the DataContext of your UserControl to this.


TemplateBinding is ok. You need to set somehow the binding source (for example through mentioned DataContext or simply in Xaml using Text attribute), but I cannot judge where's the problem since you omitted this code.

I don't know what's the purpose of this class, but probably adding some features to the standard PasswordBox. I would keep both implementations as similar as possible. What I mean the Text property should be called Password etc.

On more remark: The presented template does not need the Grid. Unless you have extra reason for using it, remove it - it just adds on the layout complexity. Note that the default template of the PasswordBox is already wrapped in an identical Grid...


I haven't been able to get this to work no matter what I do. What I did instead that does work is setting up some fake binding in code.

namespace CustomControlBinding
{
    public class PasswordBoxTest : Control
    {
        private PasswordBox passwordBox;
        private string passwordSetBeforeTemplateApplied;

        public static readonly DependencyProperty PasswordProperty = DependencyProperty.Register( "Password", typeof( string ), new PropertyMetadata( OnPasswordPropertyChanged ) );

        public string Password
        {
            get { return GetValue( PasswordProperty ) as string; }
            set { SetValue( PasswordProperty, value ); }
        }

        public PasswordBoxTest()
        {
            DefaultStyleKey = typeof( PasswordBoxTest );
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            passwordBox = (PasswordBox)GetTemplateChild( "PasswordElement" );
            passwordBox.PasswordChanged += PasswordBoxPasswordChanged;
            if( !string.IsNullOrEmpty( passwordSetBeforeTemplateApplied ) )
            {
                passwordBox.Password = passwordSetBeforeTemplateApplied;
            }
        }

        public static void OnPasswordPropertyChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
        {
            ( (WatermarkPasswordBox)d ).OnPasswordChanged( d, e );
        }

        private void OnPasswordChanged(  DependencyObject d, DependencyPropertyChangedEventArgs e )
        {
            if( passwordBox == null )
            {
                passwordSetBeforeTemplateApplied = Password;
                return;
            }

            if( Password != passwordBox.Password )
            {
                passwordBox.Password = Password;
            }
        }

        private void PasswordBoxPasswordChanged( object sender, RoutedEventArgs e )
        {
            if( passwordBox.Password != Password )
            {
                Password = passwordBox.Password;
            }
        }    
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜