Свойство зависимости WPF - PullRequest
       7

Свойство зависимости WPF

3 голосов
/ 18 февраля 2011

Я новичок в WPF, и я пытаюсь сделать то, что, по моему мнению, было бы простой задачей - отобразить значение поля в моем бизнес-объекте по мере его изменения во время моей программы.Я знаю, как «заставить» его изменить, вручную изменив свойство TextBox.Text в C #, но, изучая WPF, я хочу сделать это «правильным» способом, а это означает привязку данных.

Вопрос № 1: Насколько я понимаю, я выбрал либо использование DependencyProperty, либо реализацию INotifyPropertyChanged в моем бизнес-объекте, верно?

Вопрос № 2: Вот общая версия моего кода, в которой я попытался перейти по маршруту DependencyProperty.

Разметка:

Button x:Name="nextButton" Content="Click"  Grid.Row="2" Click="nextButton_Click" />
TextBox x:Name="myTextBox" Grid.Row="1" Text="{Binding Source=myTest, Path=Name, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}"/>

Код позади:

namespace DependencyTest2
{
    /// 
    /// Interaction logic for MainWindow.xaml
    /// 
    public partial class MainWindow : Window
    {
        private int i;

        private TestSphere myTest;

        public MainWindow()
        {
            InitializeComponent();

            i = 0;

            myTest = new TestSphere();
        }

        private void nextButton_Click(object sender, RoutedEventArgs e)
        {
            switch (i)
            {
                case 0:
                    myTest.Name = "string1";
                    break;
                case 1:
                    myTest.Name = "string2";
                    break;
                case 2:
                    myTest.Name = "string3";
                    break;
            }

            i++;
        }
    }

    class TestSphere : DependencyObject
    {

        public string Name
        {
            get { return (string)GetValue(NameProperty); }
            set { SetValue(NameProperty, value); }
        }

        public static readonly DependencyProperty NameProperty =
            DependencyProperty.Register("Name", typeof(string), typeof(TestSphere));


        public TestSphere()
        {
            Name = "default";
        }
    }
}

Когда я запускаю программу, в текстовом поле ничего не появляется, даже если свойство bound имеет значение- Есть ли что-то еще, что мне нужно сделать, чтобы предупредить привязку об изменении исходного значения?Я думал, что использование DependencyProperty в качестве источника позаботится об этом, но опять же, я новичок WPF.Спасибо!

  • Стив

Хорошо, я попытался реализовать INotifyPropertyChanged, используя класс-оболочку, который я нашел в codeproject, следующим образом:


    class TestSphere : NotifyProperyChangedBase
    {
        private string _Name;

        public string Name
        {
            get { return _Name; }
            set 
            {
                this.CheckPropertyChanged("Name", ref _Name, ref value);
            }
        }

        public TestSphere()
        {
            Name = "default";
        }
    }

    public abstract class NotifyProperyChangedBase : INotifyPropertyChanged
    {
        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion
        #region methods
        protected bool CheckPropertyChanged(string propertyName, ref T oldValue, ref T newValue)
        {
            if (oldValue == null && newValue == null)
            {
                return false;
            }

            if ((oldValue == null && newValue != null) || !oldValue.Equals((T)newValue))
            {
                oldValue = newValue;
                FirePropertyChanged(propertyName);
                return true;
            }

            return false;
        }

        protected void FirePropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion

Вотмоя новая разметка тоже:


    Grid Name="myGrid">
        Grid.RowDefinitions>
            RowDefinition Height="30"/>
            RowDefinition Height="30"/>
            RowDefinition Height="30"/>
            RowDefinition Height="*"/>
        /Grid.RowDefinitions>
        Label x:Name="myLabel" Grid.Row="0" Foreground="Black"  />
        Button x:Name="nextButton" Content="Click"  Grid.Row="2" Click="nextButton_Click" />
        TextBox x:Name="myTextBox" Grid.Row="1" Text="{Binding Path=myTest.Name}"/>
    /Grid>

Я также добавил строку myGrid.DataContext = myTest; в 'public MainWindow ()' сразу после того, как создал экземпляр myTest.Когда я выполняю пошаговую программу, значение this.PropertyChanged всегда оценивается как null, так что PropertyChanged даже никогда не срабатывает.Заранее извините за то, что, должно быть, действительно нубский вопрос.

  • Стив

1 Ответ

1 голос
/ 18 февраля 2011

Вам нужно только реализовать INotifyPropertyChanged для класса TestSphere, а не DependencyObject. По мере обновления значения звоните PropertyChanged(this, new PropertyChangedEventArgs("Name")).

Во-вторых, вам нужно установить DataContext для окна в вашем коде. Допустим, вы использовали это в своем XAML для корневого элемента сетки:

<Grid Name="MainForm">

Тогда в своем коде вы сделаете следующее:

MainForm.DataContext = this;

Наконец, измените свойство myTest на public, и привязка в вашем XAML должна быть только

Text="{Binding Path=myTest.Name}"
...