DVD
DVD

Reputation: 1784

Error Binding a property of a user control wp7

I created an user control to use it in multiple places around the app, the control have two properties, witch value are binded to the viewmodel. the problem is when the app is loading it throws an exception while setting one of the properties of the user control, any idea?

User Control.xaml

<UserControl x:Class="Client.Controls.CredentialsUserControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    d:DesignHeight="480" d:DesignWidth="480">

    <Grid Name="LayoutRoot">

        <TextBlock Text="{Binding Title}" Margin="12,20,12,390" TextWrapping="Wrap" FontSize="30"/>

        <TextBlock Text="Username" Margin="39,88,260,362" FontSize="25"/>
        <TextBlock Text="{Binding Credentials.User}" Margin="361,88,0,362" FontSize="25" />

        <TextBlock Text="Password" Margin="39,148,260,302" FontSize="25"/>
        <TextBlock Text="{Binding Credentials.Password}" Margin="361,148,0,302" FontSize="25" />

</UserControl>

UserControl.xaml.cs

public partial class CredentialUserControl: UserControl , INotifyPropertyChanged 
{

    public const string CredentialsPropertyName = "Credentials";

    private ICredentials _credentials= null;
    public ICredentials Credentials
    {
        get
        {
            _credentials_report;
        }

        set
        {
            if (_credentials== value)
            {
                return;
            }

            _credentials= value;
            NotifyPropertyChanged(CredentialsPropertyName );
        }
    }

    public string Title { get; set; }



    public MobfoxReportUserControl()
    {
        InitializeComponent();

        Loaded += PageLoaded;
    }

    void PageLoaded(object sender, RoutedEventArgs e)
    {
        this.DataContext = this;

    }


    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string prop)
    {
        if(PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
    }
}

The Usage:

<Controls:CredentialsUserControl  Title="Your Credentials" Credentials="{Binding CurrentUser}"/>

The ViewModel Property snippet is the same as the showed in the UserControl.xaml.cs

The exception being thrown

System.Windows.Markup.XamlParseException occurred
  Message=Set property 'CredentialsUserControl.Credentials' threw an exception. [Line: 29 Position: 85]
  InnerException: System.ArgumentException
       Message=ArgumentException
       StackTrace:
            at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, StackCrawlMark& stackMark)
            at System.Reflection.RuntimePropertyInfo.InternalSetValue(PropertyInfo thisProperty, Object obj, Object value, Object[] index, StackCrawlMark& stackMark)
            at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, Object[] index)

What I found out is that the origin of the exception is the binding on the MainPage, but didn't really understand why or what is causing it.

Thanks

Upvotes: 0

Views: 1093

Answers (2)

William Melani
William Melani

Reputation: 4268

You're losing the DataContext by setting it explicitly inside your usercontrol. In addition, you should use a DependencyProperty. Finally, your XAML is loaded with Exact margins... you might want to switch to use Grid Row/Column definitions, as if you ever need to change the page, it will be easier.

using System.Net;
using System.Windows;
using System.Windows.Controls;

namespace Client.Controls
{
    public partial class CredentialsUserControl : UserControl
    {
        public CredentialsUserControl()
        {
            InitializeComponent();

            if (System.ComponentModel.DesignerProperties.IsInDesignTool)
            {
                Credentials = new NetworkCredential("user","pass");
                Title = "testing creds";
            }
        }



        public ICredentials Credentials
        {
            get { return (ICredentials)GetValue(CredentialsProperty); }
            set { SetValue(CredentialsProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Credentials.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CredentialsProperty =
            DependencyProperty.Register("Credentials", typeof(ICredentials), typeof(CredentialsUserControl),new PropertyMetadata(null));

        public string Title { get; set; }

    }
}

<Grid Name="LayoutRoot">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <TextBlock Text="{Binding ElementName=control, Path=Title}" TextWrapping="Wrap" FontSize="30" Margin="12,24" />

    <Grid Grid.Row="1" Margin="40,0,0,0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="12" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <TextBlock Text="Username" FontSize="25" Grid.Column="0" />
        <TextBlock Text="{Binding ElementName=control, Path=Credentials.User}" FontSize="25" Grid.Column="1" HorizontalAlignment="Right"/>

        <TextBlock Text="Password" Grid.Row="2" FontSize="25" Grid.Column="0" />
        <TextBlock Text="{Binding ElementName=control, Path=Credentials.Password}" Grid.Row="2" FontSize="25" Grid.Column="1" HorizontalAlignment="Right"/>
    </Grid>
</Grid>

Upvotes: 1

Stuart
Stuart

Reputation: 66882

I'm not sure, but what is this block of code in your constructor:

    LayoutRoot.DataContext = this;
    this.DataContext = this;

It looks "dangerous"...

Upvotes: 0

Related Questions