Как я могу привязать к вспомогательному свойству в Silverlight - PullRequest
1 голос
/ 01 апреля 2010

Ради аргумента, вот класс простого человека

public class Person : DependencyObject, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public static readonly DependencyProperty FirstNameProperty =
        DependencyProperty.Register( "FirstName",
                                     typeof ( string ),
                                     typeof ( Person ),
                                     null );
    public static readonly DependencyProperty LastNameProperty =
        DependencyProperty.Register( "LastName",
                                     typeof( string ),
                                     typeof( Person ),
                                     null );

    public string FirstName
    {
        get
        {
            return ( string ) GetValue( FirstNameProperty );
        }
        set
        {
            SetValue( FirstNameProperty, value );
            if(PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs( "FirstName" ));
        }
    }

    public string LastName
    {
        get
        {
            return ( string ) GetValue( LastNameProperty );
        }
        set
        {
            SetValue( LastNameProperty, value );
            if ( PropertyChanged != null )
                PropertyChanged( this, new PropertyChangedEventArgs( "LastName" ) );
        }
    }
}

Я хочу создать свойство только для чтения, как это

public string FullName
    {
        get { return FirstName + " " + LastName; }
    }

Как работает привязка в этом сценарии? Я попытался добавить DependancyProperty и вызвал событие PropertyChanged для полного имени. По сути, я просто хочу иметь свойство, к которому я могу привязать, которое возвращает полное имя пользователя при каждом изменении имени или фамилии. Вот последний класс, который я использую с модификациями.

public class Person : DependencyObject, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public static readonly DependencyProperty FirstNameProperty =
        DependencyProperty.Register( "FirstName",
                                     typeof ( string ),
                                     typeof ( Person ),
                                     null );
    public static readonly DependencyProperty LastNameProperty =
        DependencyProperty.Register( "LastName",
                                     typeof( string ),
                                     typeof( Person ),
                                     null );
    public static readonly DependencyProperty FullNameProperty =
        DependencyProperty.Register( "FullName",
                                     typeof( string ),
                                     typeof( Person ),
                                     null );

    public string FirstName
    {
        get
        {
            return ( string ) GetValue( FirstNameProperty );
        }
        set
        {
            SetValue( FirstNameProperty, value );
            if ( PropertyChanged != null )
            {
                PropertyChanged( this, new PropertyChangedEventArgs( "FirstName" ) );
                PropertyChanged( this, new PropertyChangedEventArgs( "FullName" ) );
            }
        }
    }

    public string LastName
    {
        get
        {
            return ( string ) GetValue( LastNameProperty );
        }
        set
        {
            SetValue( LastNameProperty, value );
            if ( PropertyChanged != null )
            {
                PropertyChanged( this, new PropertyChangedEventArgs( "LastName" ) );
                PropertyChanged( this, new PropertyChangedEventArgs( "FullName" ) );
            }
        }
    }

    public string FullName
    {
        get { return GetValue( FirstNameProperty ) + " " + GetValue( LastNameProperty ); }
    }
}

Ответы [ 2 ]

3 голосов
/ 02 апреля 2010

Я не уверен, чего вы здесь добиваетесь, но почему ваш класс Person наследуется от DependencyObject и почему FirstName и LastName DependencyProperties? Если все, что вы хотите сделать, - это связать свойства Person с пользовательскими элементами управления в вашем представлении, достаточно иметь класс Person, реализующий INotifyPropertyChanged, чтобы заставить работать привязку данных. Обычно вы привязываете его к свойствам пользовательского элемента управления, которые являются свойствами зависимостей (например, свойство Text для TextBlock).

Попробуйте это для себя Класс человека:

using System.ComponentModel;
public class Person : INotifyPropertyChanged
{
    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

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

    #endregion

    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            if (value != _firstName)
            {
                _firstName = value;
                RaisePropertyChanged("FirstName");
                RaisePropertyChanged("FullName");
            }
        }
    }

    private string _lastName;
    public string LastName 
    { 
        get { return _lastName; }
        set 
        {
            if (value != _lastName)
            {
                _lastName = value;
                RaisePropertyChanged("LastName");
                RaisePropertyChanged("FullName");
            }
        }
    }

    public string FullName 
    {
        get { return FirstName + " " + LastName; }
    }
}

И используйте это, по вашему мнению:

<Grid x:Name="LayoutRoot" Background="White" >
    <TextBlock Text="{Binding FullName}"/>
</Grid>

Тогда в вашем коде вы можете создать его так:

public partial class MainPage : UserControl
{
    public MainPage()
    {
        InitializeComponent();

        DataContext = new Person { FirstName = "John", LastName = "Doe" };
    }
}

НТН, Фил

1 голос
/ 02 апреля 2010

Прежде всего, ваша реализация существующих свойств FirstName и LastName имеет недостатки. У объекта DependencyObject уже есть способы информировать привязки об изменениях значений, и значения могут быть изменены другим механизмом, кроме вызова методов Setter.

Мой первый вопрос: почему вообще существуют свойства зависимостей FirstName и LastName? Это кажется странным выбором для этого типа класса. Ответ Фила уже дал то, чего я действительно ожидал бы от правильного.

Однако, если ваш код на самом деле был упрощением и что на самом деле существует реальная необходимость создания свойств зависимости, вот как это должно быть сделано:

public class Person : DependencyObject, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public static readonly DependencyProperty FirstNameProperty =
        DependencyProperty.Register( "FirstName",
                                     typeof ( string ),
                                     typeof ( Person ),
                                     OnNamePropertyChanged);

    public static readonly DependencyProperty LastNameProperty =
        DependencyProperty.Register( "LastName",
                                     typeof( string ),
                                     typeof( Person ),
                                     OnNamePropertyChanged);

    private static void OnNamePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
      ((Person)d).OnNamePropertyChanged();
    }

    private void OnNamePropertyChanged()
    {
      if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs("FullName")));
    }

    public string FirstName
    {
      get { return GetValue(FirstNameProperty) as string; }
      set { SetValue(FirstNameProperty, value); }
    }

    public string LastName
    {
      get { return GetValue(LastNameProperty) as string; }
      set { SetValue(LastNameProperty, value); }
    }
    public string FullName
    {
      get { return FirstName + " " + LastName; }
    }
}
...