WPF依赖属性问题

时间:2011-02-18 14:23:29

标签: wpf data-binding dependency-properties

我是WPF的新手,我正在尝试做我认为简单的任务 - 在我的业务对象中显示字段的值,因为它在我的程序中发生了变化。我知道如何通过手动更改C#中的TextBox.Text属性来“强制”更改它,但是当我正在学习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";
        }
    }
}

当我运行程序时,文本框中没有任何内容,即使绑定属性有值 - 我还需要做些什么来提醒绑定源值已经改变了吗?我认为使用DependencyProperty作为源代码可以解决这个问题,但话说回来,我是WPF的新秀。谢谢!

  • 史蒂夫

好的,我尝试使用我在codeproject上找到的包装器类实现INotifyPropertyChanged,如下所示:


    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

这也是我的新Markup:


    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>

我在实例化myTest后立即将行myGrid.DataContext = myTest;添加到'public MainWindow()'。当我逐步执行生成的程序时,this.PropertyChanged的值总是计算为null,因此PropertyChanged甚至不会触发。提前抱歉,这是一个非常棒的问题。

  • 史蒂夫

1 个答案:

答案 0 :(得分:1)

您应该只需要在TestSphere类上实现INotifyPropertyChanged,而不是在DependencyObject上实现。在更新值时,请致电PropertyChanged(this, new PropertyChangedEventArgs("Name"))

其次,您需要在代码隐藏中为窗口设置DataContext。假设您在XAML中将此用作根网格元素:

<Grid Name="MainForm">

然后在你的代码隐藏中,你会这样做:

MainForm.DataContext = this;

最后,将myTest属性更改为public,然后XAML中的绑定只需要

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